redis数据写入mysql问题

我想问一下如果我用定时任务把redis写入到mysql,那我在查询用户的点赞列表时如何保证数据的一致性。

在使用Redis作为缓存,MySQL作为持久化存储的场景中,数据一致性是一个需要考虑的问题。以下是一些可能的策略:

  1. 双写一致性:当数据发生变化时,同时更新Redis和MySQL。这种方式可以保证数据的一致性,但是如果在更新过程中出现问题(例如,更新Redis成功,但更新MySQL失败),则可能导致数据不一致。

  2. 先写Redis,再异步写MySQL:当数据发生变化时,先更新Redis,然后通过消息队列或者其他方式异步更新MySQL。这种方式可以提高系统的响应速度,但是如果异步更新失败,也可能导致数据不一致。

  3. 只写Redis,定时同步到MySQL:这是你提到的方案,通过定时任务定期将Redis的数据同步到MySQL。这种方式可以降低对MySQL的写压力,但是在同步周期内,MySQL的数据可能是过期的。

对于你的问题,查询用户的点赞列表时如何保证数据的一致性,一种可能的解决方案是:

  • 当用户点赞或取消点赞时,更新Redis的数据,并将这个操作放入一个队列中。
  • 有一个后台任务定期从队列中取出操作,并更新MySQL的数据。
  • 当查询用户的点赞列表时,先从Redis中查询。如果Redis中没有数据(例如,Redis服务器刚刚重启),则从MySQL中查询,并将查询结果写入Redis。

这种方式可以在大部分情况下保证数据的一致性,但是如果后台任务在处理队列中的操作时失败,可能会导致数据不一致。你需要根据你的具体需求和系统的特点,选择最适合你的方案。

不知道你这个问题是否已经解决, 如果还没有解决的话:
  • 帮你找了个相似的问题, 你可以看下: https://ask.csdn.net/questions/7708106
  • 这篇博客你也可以参考下:redis做mysql的缓存,怎么把redis数据和mysql数据同步?
  • 除此之外, 这篇博客: redis进阶:mysql,redis双写一致性,数据库更新后再删除缓存就够了吗?中的 测试 部分也许能够解决你的问题, 你可以仔细阅读以下内容或者直接跳转源博客中阅读:

    最后我们来进行一个模拟测试,我们将sql中的字段故意写成不存在的字段名

    在这里插入图片描述

    请求这个接口

    在这里插入图片描述

    报错字段password2不存在

    在这里插入图片描述
    查看数据库中并没有添加成功

    在这里插入图片描述

    缓存里同样也没有,说明我们的redis支持了数据库的事物操作

    在这里插入图片描述

  • 您还可以看一下 CSDN讲师老师的分布式爬虫之数据存储开发实战课程中的 1_redis写入mysql小节, 巩固相关知识点
  • 以下回答来自chatgpt:

    针对Redis数据写入MySQL时保证查询用户点赞列表时的数据一致性的问题,可以考虑以下解决方案:

    1. 组合4(先更新数据库,再删除缓存):在更新数据库之后再删除Redis缓存数据。这种方法能够解决多线程同时更新同一条数据的问题,因为虽然两个线程完成步骤的顺序可能不一样,但是数据库最终都会以最后一次更新的结果为准。在组合3的第一个问题(第一步成功,第二步失败)和第二个问题(更新或删除出现异常)的情况下,这种方案仍有一定的概率出现一致性问题。但是相对于组合3而言,这种问题的出现概率更低。

    2. 在MySQL的数据持久化和Redis的定时写入之间增加分布式锁,保证同时只有一个线程可以进行写入操作。

    3. 在Redis的写入操作中加入事务,保证写入MySQL和Redis的操作可以同时进行,保证数据的一致性。

    以下是组合4的示例代码:

    //高并发场景可配合使用锁等机制,这里仅示例主流程代码
    public void updateData(String key, String value) {
        //更新数据库
        updateMySQL(key, value);
        try {
            //删除Redis缓存
            redis.delete(key);
        } catch (Exception e) {
            //删除出现异常,可以记录日志,不影响数据一致性,不做其他处理
        }
    }
    
    //更新MySQL的代码示例
    public void updateMySQL(String key, String value) {
        //在事务中进行MySQL和Redis的写入操作,保证同时进行
        Transaction transaction = MySQL.beginTransaction();
        try {
            //查询MySQL数据并进行更新操作
            String sql = "select * from tableName where key = ?";
            Record record = Db.findFirst(sql, key);
            record.set("value", value).update();
            transaction.commit();
        } catch (Exception e) {
            transaction.rollback();
            throw new RuntimeException(e);
        }
    }
    

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^