Redis缓存、优化

版权声明:个人博客:blog.suyeq.com 欢迎访问 https://blog.csdn.net/hackersuye/article/details/88983096

错误收集

对于Redis服务应当加入异常监控系统,以便于监视发现出现的故障,常用的思路是加入日志信息,在捕获异常时监控日志的信息等级,监测超过指定次数就出发报警程序。同样也可以引入外部的检测平台监控

避免阻塞

1. 慢查询引起阻塞

  • 原因:慢查询需要花费时间多
  • 解决办法:利用slowlog get{n}语句可以获得最近执行时间超过10ms的命令,但是线上建议将其设置为1ms,发现毫秒级以上的操作,将引起慢查询的命令禁用或者改用时间复杂度底的命令

2. 大对象引起阻塞

  • 原因:大对象使得持久化与复制会耗时很长
  • 解决办法:利用命令redis-cli -h {ip} -p{port} --bigkeys来找出redis里面含有的大对象,其原理是利用scan的扫描操作

3. 过度优化引起阻塞

  • 原因:比如过度追求内部结构ziplist的低内存消耗(即过度放宽ziplist的使用条件),会导致命令在ziplist上的执行时间变长
  • 解决办法:合理的使用类型的内部结构,转变为更为高效的结构

4. 持久化阻塞

  • 原因:由folk操作,或者AOF持久化写入硬盘时硬盘压力过大,写入需要等待引起
  • 解决办法:对于folk操作引起的阻塞应当优先使用物理机或者高效的支持folk操作的虚拟机,以及控制Redis示例最大可用内存,fork耗时跟内存成正比。对于后者,则应该对于硬盘开销的优化。比如不要和高硬盘负载的服务部署在一起。

5. 其它

由CPU竞争、内存交换、网络问题引起阻塞。

内存优化

  • 缩减键值对象:尽量减少key与value的长度,比如使用外在的序列化方式,如:jackson等,来减少内存的使用
  • 使用共享对象池:开启LRU淘汰策略后,该对象池无效,因为共享了LRU的信息。且只有整数对象池。
  • 字符串优化:小心预分配机制带来的内存浪费,即尽量减少对字符串长修改的操作如:appendsetrange
  • 合理的使用编码类型:在满足需求的前提下可以使用低内存使用率的编码结构
  • 控制键的数量:合理使用类型来减少键的使用量

缓存设计

1. 缓存的更新策略

  • LRU/LFU/FIFO算法剔除:通常用于缓存使用量超过了预设的最大值的时候。
  • 超时删除:通过给缓存设置一个过期时间。
  • 主动更新:存储层数据更新后需要对缓存层立马更新。

2. 穿透优化

缓存穿透是指:查询一个根本不存在的数据,缓存层与存储层都不会命中。该问题可能会导致后端的存储负载过大,甚至可能宕掉。有两种解决方案:

  • 缓存空的对象:在缓存层不命中,查询存储层的时候,没有命中则依旧缓存一个空的对象在存储层
  • 布隆过滤器拦截:指的是在访问缓存层之前,将存在的key用布隆过滤器提前保存起来,做第一层的拦截

3. 无底洞优化

无底洞问题指的是:投入更多的节点,系统的整体性能反而下降了。引起的原因是网络的延迟以及连接数众多,造成节点的性能下降。

4. 雪崩优化

雪崩优化是指:出于某些原因,缓存层宕掉,从而使得大量的请求到达存储层,从而使得存储层也宕掉的情况。有三个解决办法:

  • 保证缓存层的高可用:实行分布式,即使一个节点宕掉也没多大关系
  • 依赖隔离组件为后端限流并降级:即某个模块宕掉后,用其它的模块数据进行填补,常用的组件有:Hystrix
  • 提前演练:测压

5. 热点Key重建优化

热点Key重建优化是指:当前Key是一个热点Key,并发量特别大,且重建该Key指向的缓存不可能短时间完成,在这期间,有大量的请求(一个请求就够了)来重建缓存,造成后端负载过大,可能让服务器瘫痪。有两种解决方法:

  • 利用锁:用互斥锁来保证只有当前一个线程可以来重建缓存
  • 永远不过期:是指从缓存层上来看,不设置过期时间,但是在功能层上,为每个value设置一个逻辑的过期时间,当发现超过后,就用单独的线程去重构缓存

猜你喜欢

转载自blog.csdn.net/hackersuye/article/details/88983096