高并发下的缓存策略 - 3

阻塞队列

在抢单业务中,同一时间内会有大量的请求,但MySQL中的写速度总是有限的,因此就需要通过读写分离来提高响应速度。优化的内容在第二篇中已经提到过,此处主要是读写不均衡下队列的一种实现方式。

阻塞队列与其他队列不一样的地方在于,当队列为空时,若一个线程试图从队列中取出元素,那么这个操作将被阻塞,直到有元素被放入为止;当队列为满时,若一个线程试图向队列中放入元素,那么这个操作也会被阻塞,直到有元素被取出为止。也就是说,阻塞队列是一种更加智能的生产-消费者模型。

消息队列

阻塞队列也存在问题,例如超过上限时处理速度仍然较慢,而且由于没有持久化,阻塞队列中容易出现安全问题。使用消息队列就容易解决这些问题。消息队列仍然是一种更智能的生产-消费者模型。在redis中,可以通过stream类型实现消息队列的功能。当然,更常用的还是Rabbit MQ。

Feed流的实现方案

Feed流可以为用户持续提供的“沉浸式”体验,通过无限下拉刷新获取信息。而Feed流产品有两种实现方式,一种是不做内容筛选,简单的按照内容发布时间排序,常用于好友或关注。如关注栏和朋友圈等;而另一种则是利用智能算法屏蔽掉用户不感兴趣的内容,推送用户感兴趣的内容来吸引用户。

对于其中的第一种实现方式,有3种不同的解决方案

  • 拉模式
    拉模式也叫做读扩散。每个内容发布者准备一个发件箱,内容发布者在发布内容时,将内容和时间戳一起放到发件箱内。普通用户有一个收件箱。收件箱平时为空,只有在普通用户需要观看时才将所有人的发件箱消息全部拉到收件箱里去,并按时间顺序排列。
    由于收件箱是一次性的,因此该方法能节省内存。但是由于每一次读取时都要重新找发件箱内的消息,所以读取速度较慢。

  • 推模式
    推模式也叫做写扩散。与拉模式不同,每个普通用户准备一个收件箱。内容发布者向关注他的所有粉丝的收件箱。
    一份消息需要储存多次,因此内存消耗较大。但用户直接打开收件箱即可,因此读取速度较快。因此适用于用户量较少,没有大V的应用。

  • 推拉结合
    空间与时间总是不能兼容,因此需要在二者之中进行取舍。内容发布者都有发件箱,普通用户都有收件箱。对粉丝少的内容发布者使用推模式,对粉丝多的内容发布者,对活跃粉丝使用推模式,对僵尸粉使用拉模式。适合超千万的用户量,大V云集的应用。

统计

对日活量的统计可以分为两个统计指标

  • UV (Unique Visitor): 独立访客量,通过互联网访问、浏览这个网页的人。一天内同一个用户多次访问该网站,只记录一次。
  • PV (Page View): 页面访问量,用户每访问一个页面就记录一次,访问多次就记录多次。

因为对用户的统计信息需要存储,因此这种统计在服务器段做会比较麻烦,就是在redis中进行缓存,数据量也会很恐怖。因此对于UV统计,常用的方法是使用redis内置的HyperLogLog功能,该功能能确定非常大的集合的基数,但统计会有误差,误差为小于0.81%。


高并发下的缓存策略 - 3
https://ivanclf.github.io/2025/09/25/redis-3/
作者
Ivan Chan
发布于
2025年9月25日
许可协议