Set Up MySQL Master‑Slave Replication with Docker and Sync to Redis via Canal
This guide walks through installing MySQL in Docker, configuring master‑slave replication, verifying synchronization, deploying a Canal server, and integrating it with a Spring Boot application to automatically push database changes into Redis.
Environment
Spring Boot 2.7.12 + MySQL 8. Master IP: 192.168.2.129, Slave IP: 192.168.2.130.
1. Install MySQL with Docker
Create directories and set permissions:
mkdir -p /root/software/mysql/conf /root/software/mysql/data
chmod -R 777 /root/software/mysql/Run the MySQL container:
docker run --name mysql8 --restart=always --privileged=true \
-v /root/software/mysql/conf/my.cnf:/etc/mysql/my.cnf \
-v /root/software/mysql/data:/var/lib/mysql \
-v /etc/localtime:/etc/localtime:ro \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123123 \
-d mysql --lower_case_table_names=12. MySQL Configuration (my.cnf)
[client]
#socket = /usr/mysql/mysqld.sock
default-character-set = utf8mb4
[mysqld]
#pid-file = /var/run/mysqld/mysqld.pid
#socket = /var/run/mysqld/mysqld.sock
#datadir = /var/lib/mysql
#socket = /usr/mysql/mysqld.sock
#pid-file = /usr/mysql/mysqld.pid
datadir = /var/lib/mysql
character_set_server = utf8mb4
collation_server = utf8mb4_bin
secure-file-priv = NULL
symbolic-links = 0
!includedir /etc/mysql/conf.d/3. Master‑Slave Configuration
On the master (192.168.2.129) add:
binlog_format=MIXED
log-bin=mysql-bin
server-id=1On the slave (192.168.2.130) add:
log-bin=mysql-bin
server-id=2Restart MySQL on both nodes.
4. Configure the Slave Node
Check master status to obtain File and Position: mysql> show master status; Run CHANGE MASTER TO with the obtained values:
CHANGE MASTER TO
MASTER_HOST='192.168.2.129',
MASTER_PORT=3306,
MASTER_USER='root',
MASTER_PASSWORD='123123',
master_log_file='mysql-bin.000003',
master_log_pos=156,
master_connect_retry=60,
GET_MASTER_PUBLIC_KEY=1;If an error about a running slave thread appears, execute: STOP SLAVE; Note that the binary log file name may increment after a master restart (e.g., mysql-bin.000004).
Verify slave status:
show slave status\G5. Test Replication
Creating databases or tables on the master will be automatically synchronized to the slave.
6. Deploy Canal
docker run --name canal -p 11111:11111 \
-v /opt/canal/conf:/home/admin/canal-server/conf \
-v /opt/canal/logs:/home/admin/canal-server/logs \
-d canal/canal-server7. Spring Boot Integration with Canal
Add Maven dependencies:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>top.javatool</groupId>
<artifactId>canal-spring-boot-starter</artifactId>
<version>1.2.1-RELEASE</version>
</dependency>
</dependencies>Configure application.yml:
spring:
redis:
host: localhost
port: 6379
password: 123123
database: 8
lettuce:
pool:
maxActive: 8
maxIdle: 100
minIdle: 10
maxWait: -1
---
canal:
server: 192.168.2.130:11111
destination: redis # multiple destinations can be comma‑separatedDefine a data model:
public class Users {
private Integer id;
private String name;
private Integer age;
@Override
public String toString() {
return "Users [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}Implement a Canal service component:
@Component
@CanalTable("users")
public class UserServiceImpl implements EntryHandler<Users> {
private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
private final StringRedisTemplate stringRedisTemplate;
public UserServiceImpl(StringRedisTemplate stringRedisTemplate) {
this.stringRedisTemplate = stringRedisTemplate;
}
@Override
public void insert(Users user) {
logger.info("新增数据为{}", user);
try {
stringRedisTemplate.opsForValue().set("users:" + user.getId(), new ObjectMapper().writeValueAsString(user));
} catch (JsonProcessingException e) { e.printStackTrace(); }
}
@Override
public void update(Users before, Users after) {
logger.info("原来数据为{}", before);
logger.info("更新数据为{}", after);
try {
stringRedisTemplate.opsForValue().set("users:" + after.getId(), new ObjectMapper().writeValueAsString(after));
} catch (JsonProcessingException e) { e.printStackTrace(); }
}
@Override
public void delete(Users user) {
logger.info("删除的数据为{}", user);
stringRedisTemplate.delete("users:" + user.getId());
}
}With these insert, update, and delete methods, any change in MySQL is automatically pushed to Redis.
Done!
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
