redis-优化思路

redis的优化思路

优化思路

CPU 相关

使用复杂度过高命令、数据的持久化,都与耗费过多的 CPU 资源有关

内存相关

bigkey 内存的申请和释放、数据过期、数据淘汰、碎片整理、内存大页、内存写时复制都与内存息息相关

磁盘相关

数据持久化、AOF 刷盘策略,也会受到磁盘的影响

网络相关

短连接、实例流量过载、网络流量过载,也会降低 Redis 性能

计算机系统

CPU 结构、内存分配,都属于最基础的计算机系统知识

操作系统

写时复制、内存大页、Swap、CPU 绑定,都属于操作系统层面的知识

常见问题

使用复杂度过高的命令

  • 原因
    • 经常使用 O(N) 以上复杂度的命令。Redis 在操作内存数据时,时间复杂度过高,要花费更多的 CPU 资源
    • 使用 O(N) 复杂度的命令,但 N 的值非常大。Redis 一次需要返回给客户端的数据过多,更多时间花费在数据协议的组装和网络传输过程中
  • 解决方式
    • 尽量不使用 O(N) 以上复杂度过高的命令,对于数据的聚合操作,放在客户端做
    • 执行 O(N) 命令,保证 N 尽量的小(推荐 N <= 300),每次获取尽量少的数据,让 Redis 可以及时处理返回

操作bigkey

  • 解决方式
    • 尽量避免一个 key 存入过大的数据
    • Redis 提供了扫描 bigkey 的命令,执行以下命令就可以扫描出,一个实例中 bigkey 的分布情况
    • 如果你使用的 Redis 是 4.0 以上版本,用 UNLINK 命令替代 DEL,此命令可以把释放 key 内存的操作,放到后台线程中去执行,从而降低对 Redis 的影响
  • 注意事项
    • 对线上实例进行 bigkey 扫描时,Redis 的 OPS 会突增,为了降低扫描过程中对 Redis 的影响,最好控制一下扫描的频率,指定 -i 参数即可,它表示扫描过程中每次扫描后休息的时间间隔,单位是秒
    • 扫描结果中,对于容器类型(List、Hash、Set、ZSet)的 key,只能扫描出元素最多的 key。但一个 key 的元素多,不一定表示占用内存也多,你还需要根据业务情况,进一步评估内存占用情况

集中过期

  • 解决方式
    • 检查你的业务代码,是否存在集中过期 key 的逻辑。一般集中过期使用的是 expireat / pexpireat 命令,你需要在代码中搜索这个关键字
    • 集中过期 key 增加一个随机过期时间,把集中过期的时间打散,降低 Redis 清理过期 key 的压力
    • 如果你使用的 Redis 是 4.0 以上版本,可以开启 lazy-free 机制,当删除过期 key 时,把释放内存的操作放到后台线程中执行,避免阻塞主线程

实例内存达到上限

  • 避免存储 bigkey,降低释放内存的耗时
  • 淘汰策略改为随机淘汰,随机淘汰比 LRU 要快很多(视业务情况调整)
  • 拆分实例,把淘汰 key 的压力分摊到多个实例上
  • 如果使用的是 Redis 4.0 以上版本,开启 layz-free 机制,把淘汰 key 释放内存的操作放到后台线程中执行(配置 lazyfree-lazy-eviction = yes)

fork耗时严重

  • 控制 Redis 实例的内存:尽量在 10G 以下,执行 fork 的耗时与实例大小有关,实例越大,耗时越久
  • 合理配置数据持久化策略:在 slave 节点执行 RDB 备份,推荐在低峰期执行,而对于丢失数据不敏感的业务(例如把 Redis 当做纯缓存使用),可以关闭 AOF 和 AOF rewrite
  • Redis 实例不要部署在虚拟机上:fork 的耗时也与系统也有关,虚拟机比物理机耗时更久
  • 降低主从库全量同步的概率:适当调大 repl-backlog-size 参数,避免主从全量同步

开启内存大页

  • 关闭内存大页机制就可以了

开启AOF

碎片整理

网络带宽过载

其它

  • 频繁短连接

  • 运维监控

  • 使用Swap

  • 绑定CPU

缓存常见问题

缓存穿透/数据穿透

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求

通常数据缓存的机制是:缓存未命中时,从数据库读取数据,并放入缓存中。而穿透场景,会导致频繁且无意义(空的查询结果集)的数据库访问,由于空值无法进行缓存,失去了缓存的

解决方案
  • 接口层增加数据校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截
  • 在穿透场景中,可以将无效的Key键查询,在缓存中设置空值缓存,即【Key,Null】,用来避免穿透而频繁的访问数据库。空值缓存设置短有效期,如30秒(设置太长会导致正常情况也没法使用)
  • 也可以通过布隆过滤器,来进行数据访问拦截。bloomfilter就类似于一个hash set,用于快速判某个元素是否存在于集合中,其典型的应用场景就是快速判断一个key是否存在于某容器,不存在就直接返回。布隆过滤器的关键就在于hash算法和容器大小

缓存击穿

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期)。这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力

解决方案
  • 设置热点数据永远不过期
  • 接口限流与熔断,降级。重要的接口一定要做好限流策略,防止用户恶意刷接口,同时要降级准备,当接口中的某些 服务 不可用时候,进行熔断,失败快速返回机制
  • 加互斥锁

缓存雪崩

缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库

解决方案
  • 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生
  • 如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中
  • 设置热点数据永远不过期

缓存污染(或者满了)

缓存污染问题说的是缓存中一些只会被访问一次或者几次的的数据,被访问完后,再也不会被访问到,但这部分数据依然留存在缓存中,消耗缓存空间

解决方案
  • 指定最大缓存设置更大
  • 建议把缓存容量设置为总数据量的 15% 到 30%,兼顾访问性能和内存空间开销
  • 指定缓存淘汰策略

持久化相关问题

Redis启动加载流程

存在AOF
	存在
		加载AOF日志
			启动Redis
	不存在
		存在RDB快照
			存在
				加载RDB快照
					启动Redis
			不存在
				启动Redis

解决方式

  • 降低RDB fork的频率,比如可以手动来触发RDB生成快照、与AOF重写
  • 控制Redis最大使用内存(小于10G),防止fork耗时过长
  • 使用更牛逼的硬件
  • 合理配置Linux的内存分配策略,避免因为物理内存不足导致fork失败

实践经验

  • Redis中的数据并不是特别敏感或者可以通过其它方式重写生成数据,可以关闭持久化,如果丢失数据可以通过其它途径补回
  • 自己制定策略定期检查Redis的情况,然后可以手动触发备份、重写数据
  • 单机如果部署多个实例,要防止多个机器同时运行持久化、重写操作,防止出现内存、CPU、IO资源竞争,让持久化变为串行
  • 可以加入主从机器,利用一台从机器进行备份处理,其它机器正常响应客户端的命令
  • RDB持久化与AOF持久化可以同时存在,配合使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Z先生09

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值