帖子回复列表缓存优化日志

尝试写点工作日志,也算是对平日工作的一些思考和总结。这次主要谈谈刚加入贝聊时接下的一个工作任务,对帖子回复列表接口做优化。

一、业务场景

类似于论坛、社区,有各种各样的帖子,用户可以在帖子下回复互动。

二、现状

目前帖子回复列表接口只对前两页数据做缓存,缓存时间为五分钟,string数据结构。当有新回复或者其它更新操作,则删除缓存。

三、存在问题

只对前两页做缓存,其它页都是直接从DB获取,遇到比较火的帖子会有大量请求到达DB,给DB造成压力。

四、目标

在尽可能少改动的前提下,提高帖子回复列表接口的缓存命中率,让绝大部分请求都能直接从缓存返回,减轻DB压力。

五、设计

使用Redis的Sorted Sets结构缓存帖子的回复信息,回复id当score,回复信息当member。

用增量方式更新缓存,有新回复,直接追加到sortedSet。同样,若删除回复,从Sorted Sets中移走该条回复。

利用Sorted Sets的排序功能,可直接获取某一页的数据返回。

说明:

1、考虑到实际场景,这里并没有缓存某个帖子所有的回复列表。因为用户翻查回复列表,大多数集中在前面几页,后面的极少会翻到,所以我们只缓存了400条数据,按一页20条数据,即20页。如果是超出20页的请求,则直接从DB获取数据返回。

2、帖子回复列表根据回复时间排序,新帖子在前面展示。这里用id当score,是因为我们的回复列表id是自增的,严格与回复创建时间保持一致的顺序。通过ZREVRANGE命令从大到小返回。

若id非自增,可以用回复时间当score。不过时间可能存在重复,若两个回复的时间一致,在查询列表时不存在问题,只是在删除具体某个回复时,不能通过ZREMRANGEBYSCORE命令删除(相同时间不能唯一确定一条回复数据)。

六、优点

1、在更新频繁情况下,依然能保持缓存高命中率。

例如运营在搞盖楼活动时,用户都在抢楼,帖子回复列表更新频繁。如果按之前方案,则前两页缓存会处于“建立-删除-建立”这么一个循环当中,命中率很低。同时还会有大量非前两页请求,DB压力非常大。

新方案是对缓存做增量更新,即使用户拼命抢楼,也能保证前面20页的数据命中缓存,减低DB压力。

2、在访问非前两页数据时,也能命中缓存。

虽然非前两页的请求量相对要低,但在总请求量很大的情况下,穿透缓存访问DB的量还是需要考虑的。这里提供前面20页的缓存,基本覆盖绝大部分请求。毕竟用户在一个帖子下翻了几十页的回复,这种情况基本没有。同时,在产品上,最好不要提供直接跳转第几页的功能。

七、优化前后数据对比

14号上线,对比上线前后4天的统计数据如下八、可能存在的问题

1、数据一致性:

若在增量更新缓存时操作失败,则缓存数据会跟DB数据不一致。

可以通过增加重试机制,降低概率。

或者先更新缓存,发布一个消息到消息队列,异步更新DB。

2、在缓存过期的瞬间,如果并发很高,可能存在多个请求做同样的操作(从DB获取数据,再set到缓存)

可以通过设置一个全局的标记位,若标记位已设置,则只执行从DB获取数据,不需要set到缓存。保证同时只有一个线程在执行set到缓存这一操作。

当然,若不作处理,对数据也无影响。

3、同样在缓存过期的瞬间,若同时存在查询和回复帖子操作,则有可能导致数据不一致

举个例子:

线程A查询列表,发现当前缓存不存在,则从DB获取数据,然后set到缓存。同时,线程B新增一回复,发现当前缓存不存在,直接更新DB。则有可能线程A set到缓存的数据没有包括线程B新增的回复。简单画个图如下:

解决方案:

将添加回复数据记录下来,在线程A将回复列表set到缓存后执行一个回调,将新增加的回复数据更新到缓存。补充:

(1)如果线程A获取的数据已经包含了新回复数据newReply,则线程在执行回调时会重复添加newReply数据到缓存,不过Sorted Set会自动识别为同一条数据,对结果无影响。

(2)如果线程A在线程B记录下回复数据newReply前就完成执行回调操作(此时newReply数据为空),则会导致DB、缓存数据不一致。

针对第(2)种情况,可以考虑在线程A执行完“将数据列表set到缓存”操作后,延时执行回调(例如5秒),基本可以解决此类问题。

4、若业务对此类数据没有强一致性要求,则以上三点均可不考虑。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值