Redis性能调优及缓存常见问题

时间:2021-03-11 17:47:15   收藏:0   阅读:24

Redis性能调优及缓存常见问题

Redis性能调优

禁用长耗时的查询命令

禁止使用keys命令,避免一次查询所有成员

通过机制严格控制hash、set zset等结构的数据大小

将不必要的业务脱离出Redis

删除大体积数据,推荐使用unlink

Redis的多线程(6.0)

为什么之前的Redis一直使用的是单线程?

技术分享图片

为什么又在6.0之后引入了多线程呢?

总结

使用slowlog优化耗时命令

避免大量数据同时失效

使用pipeline批量操作数据

技术分享图片

客户端使用优化

使用分布式架构来增加读写速度

使用物理机而非虚拟机

缓存常见问题

缓存雪崩

缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的期间,也会给后端系统数据库带来很大压力。

缓存击穿

某个key在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来

这些请求发现缓存过期,一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮

缓存穿透

对不存在的key进行高并发访问,导致数据库压力瞬间增大,这就叫做【缓存穿透】

缓存预热

  • 直接写个缓存刷新页面,上线前手工操作一下

  • 数据量不大的时候,可以在项目启动的时候自动加载

  • 定时刷新缓存

缓存更新

缓存双写一致性

一般来说,在读取缓存方面,我们都是先读取缓存,再读取数据库的

但在更新缓存方面,我们到底应该先更新谁(Redi还是MySQL)?

操作步骤(线程A和线程B都对同一数据进行更新操作):

  • 线程A更新了数据库

  • 线程B更新了数据库

  • 线程B更新了缓存

  • 线程A更新了缓存

此时缓存中的数据并不是最新的,最新的应该是B更新的数据

操作步骤(线程A更新、线程B读)

  • 请求A进行写操作,删除缓存,此时A的写操作还没有执行完

  • 请求B查询发现缓存不存在

  • 请求B去数据库查询得到旧值

  • 请求B将旧值写入缓存

  • 请求A将新值写入数据库

此时缓存中的数据也不是最新的,最新的应该是请求A更新的数据

  • 延时双删策略,伪代码如下

    • public void  write( String  key,  Object  data){
          db.updateData(data);
          redis.delKey(key);
          Thread.sleep(1000);
          redis.deleKey(key);
      }

操作步骤

  • 用户A删除缓存失败

  • 用户A成功更新了数据

或者

  • 用户A删除了缓存

  • 用户B读取缓存,缓存不存在

  • 用户B从数据库拿到旧数据

  • 用户B更新了缓存

  • 用户A更新了数据

问题:脏数据

解决方案一:

  • 设置缓存有效时间(最简单)

解决方案二:

  • 使用消息队列 :通过数据库的binlog来异步淘汰key,利用工具(canal)将binlog日志采集发送到MQ中,然后通过ACK机制确认处理删除缓存

解决方案三:

  • 要求“缓存+数据库”必须保持一致,读请求和写请求进行串行化,串到一个内存队列中 最好不要做这种方案

.

 

 

 

原文:https://www.cnblogs.com/msi-chen/p/14517318.html

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!