MySQL Master‑Slave Replication in Docker, Sync to Redis via Canal & Spring Boot

This guide walks through setting up MySQL master‑slave replication in Docker, configuring the instances, testing synchronization, then deploying Canal and integrating it with a Spring Boot 2.7.8 application to capture database changes and push them into Redis.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
MySQL Master‑Slave Replication in Docker, Sync to Redis via Canal & Spring Boot

Environment: Spring Boot 2.7.8, MySQL 8, master IP 192.168.2.129, slave IP 192.168.2.130.

1. Install MySQL with Docker

Create directories, set permissions, create my.cnf with required settings, then run the Docker container:

mkdir -p /root/software/mysql/conf /root/software/mysql/data
chmod -R 777 /root/software/mysql/
# my.cnf content omitted for brevity

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=1

2. Master‑Slave Configuration

On the master (192.168.2.129) add to my.cnf:

binlog_format=MIXED
log-bin=mysql-bin
server-id=1

On the slave (192.168.2.130) add:

log-bin=mysql-bin
server-id=2

Restart MySQL on both nodes.

3. Configure the Slave

Check master status to obtain File and Position values:

mysql> show master status;
+------------------+----------+...
| File             | Position |
| mysql-bin.000001| 156      |

Run CHANGE MASTER TO on the slave using those 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 the slave is running, stop it first: STOP SLAVE; Verify replication with: show slave status\G Key fields Slave_IO_Running and Slave_SQL_Running should be Yes.

4. Test Replication

Creating databases or tables on the master automatically replicates to the slave.

5. 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-server

6. Integrate Canal with Spring Boot

Add Maven dependencies for Redis, Web, and canal-spring-boot-starter (version 1.2.1‑RELEASE).

<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 Redis and Canal in 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

Define a simple 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 service component to handle Canal events and write them to Redis:

@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("New data {}", 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 {}", before);
    logger.info("After {}", 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("Delete {}", user);
    stringRedisTemplate.delete("users:" + user.getId());
  }
}

With these steps, any insert, update, or delete on the MySQL master is captured by Canal and instantly synchronized to Redis via the Spring Boot application.

Done.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DockerredisSpring BootmysqlReplicationCanal
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.