【Redis】Redis如何保证和MySQL数据库的数据一致性(带你一文了解)

目录

方法一:采用事务

方法二:订阅Mysql的Binlog文件(可借助Canal来进行)

方法三:基于消息队列的同步方案


方法一:采用事务

        MySQL 支持事务,在需要保证一致性的操作中使用事务。通过将 Redis 和 MySQL 操作放在同一个事务中,并使用 ACID(原子性、一致性、隔离性和持久性)的特性,可以保证 Redis 和 MySQL 数据的一致性。

方法二:订阅Mysql的Binlog文件(可借助Canal来进行)

        CanalServer会伪装成MysqlServer从库,去订阅MysqlServer主库的Binlog文件
        Canal启动的时候会配置对应的消息MQ(RabbitMQ, RocketMQ, Kafka), 监听到Binlog文件有变化是,会把变化的sql语句转换成json格式,并作为消息内容发送到MQ中
        项目中只要监听对应MQ,就能拿到Binlog改动的内容,Json数据中有明确的操作类型(CURD), 以及对应的数据。把对应数据同步到redis即可
缺点1:canal订阅Binlog的整个操作过程是单线程的,所以面临超高并发的情况下,性能可能不太出色。当然可以部署多个Canal 与 多个消费者,但是要注意消息重复消费问题,做好幂等性校验
优点1:即使人为改数据库,也会监听到,并且也会同步
优点2:异步同步,不会对接口返回有格外延迟

方法三:基于消息队列的同步方案

        基于消息队列的同步方案,通常是将 MySQL 的更新操作通过消息队列发送到一个或多个 Redis 服务器,然后 Redis 服务器根据消息队列中的消息更新缓存中的数据。这种方案相对较为灵活,可以根据实际需求选择合适的消息队列,比如 RabbitMQ、Kafka、RocketMQ 等。  

具体实现可以分为以下步骤:

        配置消息队列,比如 RabbitMQ。可以参考 RabbitMQ 官方文档 进行配置。

        在 MySQL 数据库中配置触发器,将更新操作通过消息队列发送出去。以下是一个 MySQL 触发器的示例代码:

CREATE TRIGGER sync_data AFTER INSERT ON table1
FOR EACH ROW
BEGIN
    INSERT INTO rabbitmq_queue (message) VALUES (NEW.message);
END;

上述代码将在 table1 表中插入新数据时,向名为 rabbitmq_queue 的消息队列中插入一条消息,消息内容为 NEW.message。

        在 Redis 服务器上监听消息队列,当有新消息到来时,更新缓存中的数据。以下是一个 Java 代码的示例:

        代码使用了 RabbitMQ 的 Java 客户端库,通过监听名为 rabbitmq_queue 的消息队列来更新 Redis 缓存中的数据。

ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();

channel.queueDeclare("rabbitmq_queue", false, false, false, null);

Consumer consumer = new DefaultConsumer(channel) {
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        String message = new String(body, "UTF-8");
        // 更新 Redis 缓存中的数据
        jedis.set("key", message);
    }
};

channel.basicConsume("rabbitmq_queue", true, consumer);