通常在一个 Redis 实例能轻松应对的场景下我们会使用 1 主 1 从结构,主库通过 LVS 把自己“藏起来”,而从库是纯粹的容灾功能并不提供任何服务,所以对用户是透明的,这种情况下的主库宕机灾难太好解决了:将从库升级为主库,再用这个新的主库替换掉 LVS 下的故障主库即可完成整个容灾过程,LVS 做 rs 的切换是很快的,正常整个主库切换过程不会超过 1 分钟。
而对于一些压力很大的场景,我们常见的做法是读写分离(图 2),为主库挂载多个从库,主库在 LVS 后承载写入请求,而读取请求则由另一个 LVS 后端的多个从库共同支撑。在该结构中主库挂了又该怎么办呢?
要知道 Redis 集群主库发生变更后剩余从库数据要完全重传,一个 50G 的 Redis 重灌需要大概 70 分钟(硬件、网络环境好会快一点),而在重灌过程中实例是不可读写的,也就是无法提供读取服务了,那么唯一的办法就是在这个过程中将所有的读请求切至主库的 LVS 即可。
但是等一下,好象哪里不对?是的!我们最初为什么要把读请求分到另一个 LVS 上?因为主库撑不住啊,这下切过来刚刚换好的新主库也因为撑不住那么大的读取请求而立即挂了,多么尴尬?
所以特别大的 Redis 在运维中简直是灾难,不挂还好一挂不得了,在这种灾难场景中,多数时间运维同学只能无助的死等从库恢复什么都做不了,而此时背后可能站着 3 个开发 2 个测试 1 个产品,压力多么的大?
这里插播一件很有趣的事:
曾经我们为了合理降低开发同学在 Redis 中存放的数据体积想了无数办法,但最终效果都很差,后来我们考虑从“源头”控制。
在 360 的 HULK 云平台 2.0 版本中,最早可以申请的 Redis 最大套餐为 20G,这个套餐已经不小了,然而我们的开发同学习惯性的直接申请最大套餐(20G),后来我们没办法只能关闭了 20G 套餐的自动部署改为人工审核,结果就是我们不仅被投诉耽误开发上线时间还得乖乖通过审核。
实在没办法我们做了这样一个小改进:在申请 Redis 套餐大于 15G 的时候会弹出一个框,申请人需要在这个框里填写这个 Redis 的容量是怎么计算出来的(例如多少 key 每个 key 大概多大),之后我们发现所有的套餐申请都变成了 14G,多么奇特。
于是我们再接再厉,把这个弹框改到了套餐大于等于 8G 时出现,结果非常有趣的,之后的 90% 的套餐申请都为 7G,并且没有任何投诉我们!这心理战效果拔群。
可见在 Redis 的内存体积这一问题上,开发同学和运维同学是存在“并不尖锐”的矛盾的,大内存 Redis 可以省很多事,存更多的数据、不必太在乎过期、不用代码层拆分,而对于运维同学而言,体积越大,运维代价则越大。
如果有一个能存放巨量数据(动辄 T 级)的 Redis,无论切主还是重启都不需要重新装填数据到内存,这个矛盾点是不是就不存在了?