当然,整个过程也并非上面说起来那么简单 。
比如,GC 的策略选择,是主动 GC 还是被动 GC,抑或是两者的结合?
单次 GC 时间长短的控制?如果 GC 时间过长,必然会影响 Redis 的响应速度;过短的 GC,则会导致对象一直堆积在 Tombstone 中,内存得不到释放 。
文章插图
五、Expire -- 一致 or 不一致,这是个问题作为缓存来说,比较常见的是配置一定的缓存过期策略 。一方面,可以保障数据的新鲜程度,另一方面无限制地将数据存入缓存,不仅不利于缓存的查询速度,对于资源来说也是不小的开销 。所以,Redis 中引入了 Expire 的过期机制,给每一个缓存的 Key 设定一个过期时间是一个良好的习惯 。
但是,在加入双向同步的架构之后,expire 似乎成为了一个问题,要不要将过期时间保持一致?如果保持一致的话,应该采取怎样的数据结构?
首先,我们应该确认一个问题,缓存的过期时间不一致,会不会导致数据一致性的问题?结合 Redis 的实现来说,缓存过期时间不一致,不会带来数据一致性的问题(这个数据特指除过期时间之外的用户数据) 。要说明白这个道理,我们先来看一下 Redis 是如何过期数据的 。
Redis 的过期策略简单来说分为两种,一种是主动过期,以一个固定的频率轮询存储过期时间的字典,发现有 key 过期就执行删除操作;另一种是被动过期,在用户对 key 操作时,同时判定一下 key 的过期时间,是否需要过期掉 。
两种过期策略,都由 master 发起,slave 本身通过被动接受 master 同步过来的 delete 操作,来达到数据一致性(这里我们忽略 slave-read-only 为 false,且有客户端过期 key 写入的场景) 。其实这个状态下,是存在已经过期,但是在内存中没有被删除的 key,这个时候访问 Redis,外在的表象为 key 不存在 。那么对于客户端来说,数据是一致的,过期的 key 确实拿不到了(虽然 Redis 内存中可能还有) 。
对于双向同步来说,如果并发地在两端的 Redis 执行 expire 操作,就会发生冲突,是否处理冲突,如何处理冲突,是我们这里想要讨论的点 。
在我们实际实现的过程中,曾经有一个版本确实实现了 expire 多个 Redis 之间的一致性,但是这样做,引入了更多的数据结构来解决冲突处理问题 。对比普通版本的 Redis,同样大小的 expire 数据量,内存要多出一倍 。对于携程这样 Redis 重度依赖的用户来说,内存的增加无疑伴随着大量费用的上升 。所以最终的实现上,我们并没有采取 expire 时间一致性的策略 。
那么是不是 expire 时间不一致,数据就有问题了呢?当然不是 。举例来说,有 A/B 两个 Redis 建立了双向同步 。A/B 在同一时间点,分别对同样的 key 设置了不同的过期时间(如下图) 。
一边设置过期时间为 30s,另外一边设置为 60s,互相同步之后,时间进行了对调 。30s 以后 Redis-A 上面的 key 过期,触发了 del 操作,同时把这个操作传播给 Redis-B,因为 delete 机制的存在,两边的数据是一致的 。
文章插图
缓存过期(Expire)这一小节,先分享到这里 。实现的过程中,我们还对过期策略进行了优化,防止并发地过期删除操作,造成不必要的网络开销 。
六、总结本文试着从一个个具体的小例子出发,带大家 review 一个分布式的 K/V 系统是如何搭建起来的 。后续还将带来内存优化篇 -- ZGC 的 colored pointer 在携程 Redis 的灵活运用 。
【作者简介】Nick,携程软件技术专家,关注分布式数据存储以及操作系统内核 。
更多携程技术人一手干货文章,请关注“携程技术”微信公众号 。
【五大实例详解,携程 Redis 跨机房双向同步实践】
推荐阅读
- 甘舒茶的功效与作用,详解玫瑰花茶的功效
- Java 分布式任务调度平台:PowerJob 快速开始+配置详解
- 分享五大茶叶销售技巧,鲜为人知的泡茶技巧分享
- 时间序列金融数据预测及Pandas库详解
- 详解送戒指的含义
- 福建白茶区土壤详解,安吉白茶和福建白茶有什么区别
- 茯茶保存五大忌,茯茶正在重新焕发活力
- 隔夜茶的误区,品茶五大误区
- tracert命令详解
- 网络工程师快速入门---网络架构及传输介质详解