计数与消息推送

434 阅读5分钟

1.计数数据如何存储和展示

1.1 本次主要包括 帖子的评论数、点赞数、转发数、浏览数;用户的粉丝数、关注数、发布帖子数。由于用户维度的数据(尤其是粉丝数大),在很多场景下,我们都需要查询计数数据,计数数据访问量巨大,很容易造成并发瓶颈和数据库压力过大。

1.2设存储帖子维度(评论计数,转发数,点赞数等等)的数据,建立为如下Sql

select comment_count,forward_count,like_count where table1 where id = 1

在数据量和访问量都不大况下,这种方式最简单,直接修改数据库即可

update table1 set comment_count = comment_count + ? where id = 1

但是,如果数据量很多,并且并发很高的情况下,对同一条数据进行高并发的 update操作,会因为行锁,造成数据库的性能急剧下降,此时我们就需要用到消息队列进行削峰,就是当我们增加一个评论数的时候,可以把多个SQL语句进行合并,例如

update table1 set comment_count = comment_count + 1 where id = 1
update table1 set comment_count = comment_count + 1 where id = 1
update table1 set comment_count = comment_count + 1 where id = 1 

合并多个消息内容为 :

update table1 set comment_count = comment_count + 3 where id = 1 

以上数据用数据库进行存储和计算,难免会比较慢,对数据库的事务操作还是比较多的,可以通过使用redis做数据临时存储,在定时把Redis的数据落库,查询的时候 可以获取数据库中的 comment_count + redis_vlaue,返回给前端,但是这样如果要排序就不会那么准确

1.2 未读计算的统计,主要是包括了,当有人回复你的消息,回复你的帖子,点赞你的帖子或者消息,你会收到对应的未读提醒,这个时候可以在Redis中设置自己的key,当有人回复你的帖子,可以增加你的回复未读数,当你点击了未读列表,就可以将Redis的Key重置。

1.21 但是如何实现系统消息的未读数量,假设现在有3个用户,那么就是要

for (userIds) {
   redis.set(key,value)
}

通过遍历所有的用户数量进行给每个用户的系统消息Key增加未读数量,但是这样会有一个致命的问题,假设有几百万,几千万用户的时候,这种操作是十分耗时的,就算通过多线程等等加速手段,也无法避免一个问题,那就是在大量用户中,只有可能不到一半的活跃用户是需要接收消息的,那么我们对资源就是进行了很严重的浪费,所以就不能用上面的方法进行计数。

解决办法

由于系统通知是对所有用户共享,因为每个人最近看到的消息不同,所以每个人会有不同的未读数。因此,可以记录一下在这个列表中每个人看过最后一条消息的 ID,然后统计这个 ID 之后有多少条消息,这就是未读数了,比如最近看的是系统通知4,那567就是没看过的,未读数就是 >4的就是 3

系统通知1
系统通知2
系统通知3
系统通知4   假设这个是最近看过的
系统通知5
系统通知6
系统通知7

还有一种场景,就是打红点的功能,也是一种通知全量用户的手段,如果逐个通知用户,那速度慢的让人是无法接受的,比如下面,飞车播报,后台运营新增一个内容,然后给全部的用户打红点;

default.jfif

我们可以这样做,我们可以记录一个时间,这个时间是运营最近的一次打点时间,如果给全体用户打点,就更新这个时间戳,并且每个用户会产生一个Key,去记录最近一次的点击红点栏目的时间,

运营设置红点时间
redis set admin_red_time 10012012122

用户最近一次点击红点的时间
用户1 redis_key value 10012012100
用户2 redis_key value 10012012101
用户3 redis_key value 10012012166

判断用户时间 >= 运营红点时间 == true ? 无红点 : 有红点,另外要注意,假设用户是新用户,redis_key不存在,那么就要显示红点

1.22 针对粉丝对关注多个主播的未读数的计算

当一个博主发了一个文档,那么你的关注里面里面就会显示她的栏目未读数1,以此类推,这个时候如果给每个关注的粉丝增加一个未读数,那么也会造成上面的问题,关注量大怎么办,都是僵尸粉怎么办,浪费了空间和时间,并且如果前端和后端保持心跳链接,然后不间断的更新未读数数量,那么我们的项目很快就会进入瓶颈期,解决方案也非常简单

解决方案

  1. 给博主增加一个Redis_key,记录这个博主的发布文章数量,每次发布,key+1即可
  2. 给每个用户针对关注的博主增加一个Redis_key,当他点击了博主的栏目,就把博主的Redis_vlaue更新到用户的Redis_Key中,假设用户关注的 Q W E 三个博主,那么 他的总未读数就是
graph TD
用户A --> Q发布数量-value_10 -->用户A阅读数量_5
用户A --> W发布数量-value_9  -->用户A阅读数量_6
用户A --> 发布数量E-value_8  -->用户A阅读数量_7

那么用户A的全部未读数就是 (10-5) + (9-6) + (8-7) = 9 那么用户A针对单个人的,例如Q,那就是 (10-5) = 5,直接返回给前端就好了,数据库中也不需要记录很多数据,针对很多的僵尸粉也不需要有存储浪费