如何解决redis中过期问题?(第一章)

最近我们在Redis集群中发现了一个有趣的问题。在花费大量时间进行调试和测试后,通过更改key过期,我们可以将某些集群中的Redis内存使用量减少25%。

Twitter内部运行着多个缓存服务。其中一个是由Redis实现的。我们的Redis集群中存储了一些Twitter重要的用例数据,例如展示和参与度数据、广告支出计数和直接消息。

                                                                           1、问题背景

早在2016年初,Twitter的Cache团队就对Redis集群的架构进行了大量更新。Redis发生了一些变化,其中包括从Redis 2.4版到3.2版的更新。在此更新后,出现了几个问题,例如用户开始看到内存使用与他们的预期或准备使用的内存不一致、延迟增加和key清除问题。key的清除是一个很大的问题,这可能导致本应持久化的数据可能被删除了,或者请求发送到数据原始存储。

                                                                          2、初步调查

受影响的团队和缓存团队开始进行初步的调查。我们发现延迟增加与现在正在发生的key清除有关。当Redis收到写入请求但没有内存来保存写入时,它将停止正在执行的操作,清除key然后保存新key。但是,我们仍然需要找出导致这些新清除的内存使用量增加的原因。

我们怀疑内存中充满了过期但尚未删除的key。有人建议使用扫描,扫描的方法会读取所有的key,并且让过期的key被删除。

在Redis中,key有两种过期方式,主动过期和被动过期。扫描将触发key的被动过期,当读取key时, TTL将会被检查,如果TTL已过期,TTL会被删除并且不返回任何内容。Redis文档中描述了版本3.2中的key的主动过期。key的主动过期以一个名为activeExpireCycle的函数开始。它以每秒运行几次的频率,运行在一个称为cron的内部计时器上。activeExpireCycle函数的作用是遍历每个密钥空间,检查具有TTL集的随机kry,如果满足过期kry的百分比阈值,则重复此过程直到满足时间限制。

这种扫描所有kry的方法是有效的,当扫描完成时,内存使用量也下降了。似乎Redis不再有效地使key过期了。但是,当时的解决方案是增加集群的大小和更多的硬件,这样key就会分布得更多,就会有更多的可用内存。这是令人失望的,因为前面提到的升级Redis的项目通过提高集群的效率降低了运行这些集群的规模和成本。

                                                                   3、 Redis版本:有什么改变?

Redis版本2.4和3.2之间,activeExpireCycle的实现发生了变化。在Redis 2.4中,每次运行时都会检查每个数据库,在Redis3.2中,可以检查的数据库数量达到了最大值。版本3.2还引入了检查数据库的快速选项。“Slow”在计时器上运行,“fast” 运行在检查事件循环上的事件之前。快速到期周期将在某些条件下提前返回,并且它还具有较低的超时和退出功能阈值。时间限制也会被更频繁地检查。总共有100行代码被添加到此函数中。

                                                                 4、  进一步调查

最近我们有时间回过头来重新审视这个内存使用问题。我们想探索为什么会出现regression,然后看看我们如何才能更好地实现key expiration。我们的第一个想法是,在Redis中有很多的key,只采样20是远远不够的。我们想研究的另一件事是Redi 3.2中引入数据库限制的影响。

缩放和处理shard的方式使得在Twitter上运行Redis是独一无二的。我们有包含数百万个key的key空间。这对于Redis用户来说并不常见。shard由key空间表示,因此Redis的每个实例都可以有多个shard。我们Redis的实例有很多key空间。Sharding与Twitter的规模相结合,创建了具有大量key和数据库的密集后端。

                               

发布了53 篇原创文章 · 获赞 61 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_40884473/article/details/90694434