为了账号安全,请及时绑定邮箱和手机立即绑定

有关缓存高可用性的思考

标签:
架构

webp

今年上半年,系统一直在重构,所以上半年,我的思路基本上就是按照展示层、业务层、缓存层和数据库层,这四个层次来和团队一道分层来梳理可以优化的点。对于展示层,我们H5,iOS和Android端做了很多组件化的工作;业务层的优化工作主要是微服务化的改造,这两块,我后续会开专题一一讨论。对于数据库层改造的部分工作,大家可以参考我之前写的,今天我的话题会放在缓存层上,和大家分享一下我过去几个月做的思考。

1. 缓存记录不规范,增大系统开销

我去年加入团队后,发现一个比较严重的问题:一些同学喜欢把各种数据扔在缓存里,缓存里的数据格式缺乏一个统一的规范,甚至有一些KV的记录有几百k的大小,但在实际读的时候,只会用到这条记录的某几个字段,意味着程序需要从缓存去读取记录,然后再通过代码从记录中拆解出需要的字段。这就造成了我们使用了缓存,但系统开销反而比,直接从数据库对应的表中读取这个字段更大了。更可怕的事情在于,大家开始习惯制造更多“大而全”的缓存记录。

2. 缓存的命中率不高,DB的压力没有得到足够的缓解

由于第1点的原因,当缓存单个对象数据的时候(例如:单个用户的在投金额),只有当该对象对应的数据发生变化时,我们才需要更新缓存或者让移除缓存。而当我们用一条记录缓存用户的所有属性的时候,其中任何一个对应的数据发生变化时,都需要更新或移除缓存,从而导致缓存命中率会降低,查询完缓存还需要再去查询数据库,系统的负担依然在那里。

缓存数据规范化的解决方案

由于#1和#2的原因,以及前一篇提到的缓存中的坑,缓存数据规范化处理已经到了刻不容缓的时候了。所以,根据我们自身的业务,先对现有缓存数据进行了分类:

强一致性缓存:无法接受从缓存拿到过期的数据 (比如用户的在投金额/余额)

弱一致性缓存:能接受在一段时间内从缓存拿到过期的数据 (比如产品的销量/总的购买人记录)。

不变型缓存:缓存key对应的value不会变更(比方说公司用户基本属性)。

反过来说,这三种缓存类型对应了“核心业务数据”,“产品/订单相关数据”,“非业务普通数据”。所有的缓存数据的存储和分类,也是依赖于这个准则。对于缓存粒度的控制,业务层定义的基本对象,保证比较高的缓存命中率。

缓存集群的分类管理

做好缓存的数据类型分类后,我们就可以灵活的管理我们的redis缓存集群:

1. 如果对应的业务库中的数据,需要有强一致性缓存要求, 那么redis开RDB/AOF持久化,保证数据不会丢失,硬件上选用SSD的硬盘。实时的读写全部走redis,然后异步回写到数据库。由于redis集群是不能100%保证强一致性的,有些访问量不高的重要数据,建议直接读写数据库,来保证强一致性。 

webp

2. 对于弱一致性的缓存的要求,那么高可用变成了首要任务,在配置上面,会保证集群的稳定性,比方说,对于redis cluster:

a) 默认的cluster-node-timeout为15s,可以适当增大;

b) 避免使用会引起长时间阻塞的命令,比如save/flushdb等阻塞操作,或者keys pattern这种慢查询。

3. 对于不变型缓存,会单独做一个小的集群,有一个定时任务,如果数据库发生了数据改动,会主动更新缓存,同时也会定期做一次同步。

本文中提到的redis cluster服务平台化,包括里面的细节和坑就不在这里展开谈了,网上有很多资料可以查询,如果有必要,我后续也会写一篇自己经历过的redis cluster的使用心得和踩过的坑。



作者:ForestXie
链接:https://www.jianshu.com/p/fc91c6d4a25f


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消