• 【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 触发器的示例代码:

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

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

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

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

    1. ConnectionFactory factory = new ConnectionFactory();
    2. factory.setHost("localhost");
    3. Connection connection = factory.newConnection();
    4. Channel channel = connection.createChannel();
    5. channel.queueDeclare("rabbitmq_queue", false, false, false, null);
    6. Consumer consumer = new DefaultConsumer(channel) {
    7. @Override
    8. public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
    9. String message = new String(body, "UTF-8");
    10. // 更新 Redis 缓存中的数据
    11. jedis.set("key", message);
    12. }
    13. };
    14. channel.basicConsume("rabbitmq_queue", true, consumer);
  • 相关阅读:
    Spark 中的分桶分化
    函数中使用sizeof(arr) / sizeof(arr[0])求数组长度不正确的原因
    爬虫的法律风险是什么?以及合法使用爬虫技术的建议。
    LLM RAG系列
    OpenCV每日函数 计算摄影模块(5) 无缝克隆算法
    TiSpark 原理之下推丨TiDB 工具分享
    简介undo log、truncate、​以及undo log如何帮你回滚事物?
    一文搞懂傅里叶级数与变换
    Layui数据表格的使用及其ajax异步请求
    根据产品名称返回价格(同步和异步实现)
  • 原文地址:https://blog.csdn.net/miles067/article/details/132780904