大家好,我是小趴菜,最近有一个需求,便是之后有新功用上线,那么用户在登录以后需求给个弹窗,主要是为了提示用户,渠道新增了这么一个功用,当然用户弹了一次之后,后续就不必再弹了

当然后续有新功用上线仍然是需求弹的,需求便是这样,其实也蛮简略的对不对???

接下来咱们就一步一步的来设计一下,该怎么完成这个功用

完成流程

做什么需求都是需求把流程搞理解的,不然后面麻烦就大了,

  • 1:用户登录,判别这个用户对应的这个新功用对应的弹窗是否有弹过
  • 2:假如有弹过,就回来给前端一个状态值,就不需求弹了,比方 {“功用ID”:1,”是否弹过”:1}
  • 3:假如没有弹过,那么回来前端一个{“功用ID”:1,”是否弹过”:0}
  • 4:前端拿到这个json数据,判别是否弹过,然后再根据新功用的ID来弹出对应的弹框就行了

数据库存储计划

首要咱们会想到,在数据库建一张新功用的表,然后再建一张用户与新功用之间的相相联系表

新功用表:obility
id:新功用的主键
obility_name:新功用的名称
obility_desc:新功用的描述
用户与新功用的相相联系表:obility_user
id:主键
user_id:用户ID
obility_id:新功用的id
is_open:是否弹过 0:没有,1:弹过了

那么判别的流程是这样的

  • 1:拿到这个登录的用户的user_id
  • 2:去数据库查ubility_user表,找到这个用户一切的is_open=0的记载
  • 3:假如查询不为空,那么这些便是这次用户需求弹的弹窗

现在用户登录进来,首要拿到这个登录用户的ID,然后去obility_user表中查询出这个用户有哪些新功用的弹窗没有弹出来过

select * from obility_user where user_id = 1 and is_open = 0;

咱们拿到这个用户一切没有弹过的新功用,然后进行拼接一同回来给前端就行了,好了,这个功用其实到这也就完成的差不多了

可是这种计划会不会存在什么坏处呢???

坏处一:数据量问题

其实在用户量小,并且你的新功用确认不会许多的时分,这种方法确实是能够完成的,因为数据量不是很大,后续加个索引查询也没什么问题

假如现在你的用户量很大,比方说有1000万,这时分加一个新功用,那么你这张obility_user表就会有1000万的数据,那假如有10个新功用,那便是1亿的数据,这时分单表必定满足不了咱们的事务了,所以你会选用分表来做,这时分的就要引进分库分表的中间件了,总的来说完成太杂乱了

坏处二:数据同步问题

并且这种计划其实还有一个坏处,便是咱们查询的时分,这个时分这个新功用与用户的相相联系记载是现已存在表内的,也便是说咱们在发布一个新功用的时分就要把一切用户跟这个新功用的相相联系都要同步到obility_user这张表中,不然用户登录的时分是查不到,那么也就不会有弹窗了

所以你还要保证这个新功用与一切用户的相相联系记载都成功保存到obility_user这张表中,当然少量的数据丢失也没什么影响,那这时分你是不是还要再做个数据同步的功用??

还有数据同步是需求时间的,假如你有几千万的数据,对吧,一切记载维护好需求10分钟时间,这时分有个用户登录进来了,可是这个新功用与这个用户的相相联系还没保存到数据库中,这时分就不会弹这个弹窗,然后这个用户发现有这个新功用就运用了,后续用户再登录的时分,这时分这个新功用与这个用户的相相联系保存到数据库了,这时分就会弹出这个弹窗,关于用户来说就有点体会不好了

数据库存储计划-优化

之前的计划中咱们发现要完成起来太麻烦了,比方数据量大需求分库分表,还要做数据同步,还有数据推迟的问题

之前查询的是ubility_user表,然后拿到这个用户一切 is_open这个字段等于0的数据

select * from obility_user where user_id = 1 and is_open = 0;

这时分咱们换种查询流程

  • 1:获取登录用户的user_id
  • 2:仍是去查ubility_user这张表,查询出这个用户与哪些新功用现已存在相关记载了
  • 3:与ubility表做对比,判别这个用户还有哪些新功用不存在这个相关记载的
  • 4:那么不存在相关记载的这些新功用便是这次用户要弹的弹窗了
  • 5:用户弹窗之后,在ubility_user表刺进这几条相相联系的记载

比较于之前的计划,这时分咱们发布一个新功用就不需求提前做好用户与新功用的相相联系了,咱们把这个流程放到登录的时分判别了,那么也就不会存在数据推迟的问题了

并且这个计划能够在一定程度上减少咱们ubility_user这张表的数据量,试想一下,体系里边有100万的用户,莫非这100万的用户真的都是真实用户吗?莫非就没有一些所谓的僵尸用户???

其实这个所谓的僵尸用户是不会登录咱们体系的,这些用户不登陆,那么ubility_user这张表就不会存他们的相相联系了

可是仍然没有解决数据量的问题,即便除了那些僵尸用户,真实用户仍是有许多,后续你的新功用多了,ubility_user这张表的数据量仍是有许多,仍是避免不了要分表

运用redis来存储

细心想想,其实咱们只需求知道用户在登录的时分这个新功用的弹窗有没有弹出来过,无非便是弹过,没弹过两种,那么redis中的bitmap数据类型就很符合咱们的事务了,咱们一个新功用就树立一个新的bitmap,KEY呢便是这个新任务的ID,每个用户对应着一个bit位,假如这个用户对应的这个任务上的值是0,那么就没有弹过,弹窗之后把这个对应的用户的值改成1就能够了

这样后续即便有多个新任务也便是多几个bitmap而已,咱们也不需求运用数据库来存储,也不必考虑后续数据量多了还要分库分表了,简略多了

并且即便redis有些时分丢了一点数据也无所谓,大不了就再弹一次嘛,关于用户来说其实影响也不大的