Redis与MySQL数据一致性和3大缓存问题

1.数据一致性

策略一
  1. 方案:对于写操作先插入数据库,在进行同步redis;对于更新、删除操作先,先删除缓存在操作数据库。
  2. 弊端:写入的操作需要手动同步到redis;更新的时候在高并发的情况下会出现脏数据,有可能缓存删除了之后,数据库还没更新的时候,有请求进来会查到老数据。
策略二
  1. 方案:延时双删,先删除redis中的缓存,然后在更新数据库,让线程等待1s,然后在删除redis中的缓存
// 伪代码
redis.del(key)
mysql.update(data)
Thread.sleep(1000)
redis.del(key)
  1. 弊端:不是适用于高并发,而且在没有第二次删除缓存之前仍然会有可能出现脏数据,线程等也会导致请求耗时过长
策略三
  1. 方案:修改redis的缓存时间,等到数据写入数据库之后在删除redis中的缓存
// 伪代码
redis.expire(key, 2)
mysql.update(data)
redis.del(key)
  1. 这种方案优化了请求耗时过长,即使没删除缓存,key的有效期也会到了也会重新获取数据
策略四
  1. 方案:使用MySQL中binlog的同步机制,当数据库中出现写、改、删的时候将数据异步写入redis。阿里提供了开源项目Canal,模仿了MySql的主从复制
  2. 弊端:会导致MySql的binlog文件占用磁盘过大

2.缓存

1. 缓存穿透
  • 原因:请求访问的数据redis中没有,数据库中也没有,所以没有访问数据库的结果加入到缓存中,就会一直请求数据库,数据库压力增加
  • 案例:黑客攻击
  • 解决方案:
    1. 空值缓存:如果数据库中查不到结果就将null存入到redis缓存中
    2. 布隆过滤器:它会在缓存前面加了一层过滤,过滤的规则是只允许数据库存在的数据进行下一步操作
2. 缓存击穿
  • 原因: 请求访问的数据redis中没有,数据库中有,高并发情况下会有多个请求同时访问数据库,数据库压力增加
  • 案例:热点数据过期
  • 解决方案:
    1. 加锁:同时只能有一个请求访问数据库,单线程可以使用普通锁,多线程可以使用redis分布式锁
    2. 将数据设为永久有效
3. 缓存雪崩
  • 原因:缓存的数据同时过期,或者redis宕机,导致大量请求直接访问数据库,数据库压力增加
  • 解决方案:
    1. 将缓存时间增加区间随机值
    2. 使用多级缓存
    3. 配置高可用缓存(redis集群),宕机之后尽快重启redis,通过持久化恢复数据
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章