雪花算法结合redis有序列表score的思考

1.使用redis的zset存储,最多储存200条,设置定时任务将多余的点赞信息存入数据库
2.score为处理后的messageId
key设计:user:like:userId:messageType,值为messageId,score为messageId(处理过后的)

为什么score设计为messageId,而不是时间戳?

答:我想实现这样一个效果,当判断用户是否点赞时,可以比较当前messageId与redis该用户的zset中最小的score进行比较

  1. 若该messageId经过处理后的值小于最小的score值,这时无法判断是没点赞还是缓存缺失,需要到数据库中进一步查询。
  2. 若该messageId经过处理后的值大于最小的score值,这时可以判断一定是没有点赞!!!
3.为什么是处理后的messageId?

答:因为redis中zset的score为double类型,而messageId是用雪花算法生成的,为Long类型,强行转化会产生精度丢失,这个精度丢失对我们的业务来说是不可以容忍的(看上一条的实现效果,有时会导致有没有点赞的错判)

雪花算法Id:

image-20231207111704350

double:

bb

double尾数位为52位,Long为64位,差了12位,自然会产生精度丢失,怎么解决呢?

解决方法:

对雪花算法生成的id进行处理,产生一个52位的数,这样就不会精度丢失了,也就是要去除12bit,去除最高位1bit,去除工作机器id10bit,还有1bit需要去除

  • 去除序列号最高位可行性分析:

    1. 因为雪花算法的时间戳是毫秒级的,同一个机器id可以在一毫秒生成212=4096个id,我们的业务**到不了这么多的发帖量**,去掉一位后,一个机器可以一毫秒生成211=2048个id,完全够用了!!!
    2. 但是,一个机器超过了2048个发帖,也就是低11位重置了变得很小,在这个需求中,在去zset比较时,假设最后一条是大变小,要判断的messageId大变小没事(本来可以在redis中判断是否点赞,现在必须去数据库中),小变大有问题(本来一定要去数据库查的,而因为大于最小score并且找不到messageId而被认为未点赞),但是这种情况发生的概率太低,发生条件必须是,同一用户在近两百条点赞中,点赞了在同一机器同一毫秒产生的两个id,并且这两个id一个序列号<=2048,一个>2048
  • 去除时间戳最高位可行性分析

    1. 雪花算法的时间戳为41bit,大概可以用69年

      image-20231207130047828

      去除最高位的一位,也能保证可以使用34年

      image-20231207130240405

      在用户的点赞列表中,只保存200条数据,34年后的文章的score会变的很小,也就是34年后这个点赞列表的方案就会失效

最后综合考虑,采取的方案为去除序列号最高位的方式。

歪打正着:

在仔细思考过后,我发现如果不去除10bit的工作机器id,第二点的想法(score为messageId)还有小小的瑕疵,在同一毫秒,由工作机器id大的机器生成的id总是排在工作机器id小的机器生成的id后面,这一点有一些不好!

歪打正着更正:

大的机器生成的id总是排在工作机器id小的机器生成的id后面,这一点有一些不好!

歪打正着更正:

这个想法是错的,雪花算法的后22位完全没有时间的意义,不存在某个机器生成的id永远比另一个机器生成的id大的情况!!!因为高位为时间戳,只有可能出现在同一毫秒内存在某个机器生成的id永远比另一个机器生成的id大。

有错误欢迎指正!!!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值