微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

分布式流水生成

一、前言:

在分布式高并发环境下,有些时候我们需要生成一些包含业务逻辑性的唯一标识,例如订单编号:可能由业务字符 +当前时间+唯一字符串 : ZFB:(支付宝)+20220819+000001,这个时候就我们需要保证在高并发情况下后六位数字不重复。

二、高并发下生成唯一流水标识的方式:

1.利用UUID生成唯一流水。
优点是本地生成生成无规则,缺点是不能满足业务需求,但是字符串是随机的,不利于检索和排序。
2.基于数据库自增生成唯一流水。
优点是实现简单,id是有序的,对于有排序需求的比较有利,缺点是每次生成唯一标识 都需要访问数据库增加数据库的压力。
3.基于redis生成全局唯一流水。
多个集群之间增加步长来避免生成id重复的问题,如有5台redis
第1台生成:1、6、11、16
第2台生成:2、7、12、17
第3台生成:3、8、13、18
第4台生成:4、9、14、19
第5台生成:5、10、15、20

优点是性能比较高,生成的数据是有序的,对排序业务有利,缺点是依赖于redis,需要系统引进redis组件,增加了系统的复杂性。
4.SNowflake雪花算法生成唯一流水
优点依赖于系统时钟的一致性,缺点如果某台机器的系统时钟回拨,有可能造成ID冲突,或者ID乱序)。
5.美团的号段算法生成全局唯一流水。
可以理解成在数据库获取一个范围值(比如一次获取0-1000),数据缓存到本地,每次用的时候只需要+1。本地用完后,再从数据库获取一个范围值。重复循环,直到获取设置的最大值。

三. 接下来咱们就具体来谈谈第5种,号段算法生成唯一流水的方式。

这里咱们只说思路,需要具体实现的小伙伴可以私信我。

1,咱们分布式项目在启动的时候,会自动加载获取号段的线程,启动通过业务类型,在数据库查询查询成功,存入变量中,每次请求获取id的时候,对号段id进行+1,这+1是才有juc并发包下的操作的,保证累加的时候线程安全性。+1操作完成后,把值赋值给我流水id,这个流水id就是我们分布式流水id。
2.具体获取号段原理,通过业务类型查询出配置信息,使用修改语句:最大id=最大id+步长,条件是业务类型+版本号。,修改成功,版本号+1,并且获取号段,如果没有修改成功,则进行重试,重试操作为通过业务类型再次查询配置,再次通过修改语句获取号段,修改成功即获取号段,未修改成功,则再次重试。
3.流水日期更新原因,项目中,在项目启动和每次获取分布式流水id时,均会检查日期。启动会检查配置的日期和数据库系统的日期是否匹配,如果不匹配,则会以数据库日期为准,更新数据库日期。否则则通过;每次获取的分布式流水id,均会判断当期的号段是否可用,如果可用,则直接对号段id进行原子性的累加后,赋值给流水id。如果号段不可用,不可用的情况,有当期号段已经使用达到规定的界点了。此时如获取流水时,同样是直接对号段id进行原子性的累加后,赋值给流水id,同时还会开启异步线程,去获取下一批的号段区间。
4.号段使用界点,首先要说的,这个美团的号段算法生成分布式id是双段缓存的,这样做到了高可用,每次获取流水id都是基于内存操作,业务线程不会实施操作数据库。比如当前号段的加载因子为0.2,步长为1000,首次项目启动时,会加载【0,1000】到内存中,当使用到第199的id时,第200个id时会开启异步线程获取下一批号段,此时项目中已经有两段缓存了,第一段是【800,1000】,第二段【1001,2000】提供使用,如此循环。

原文地址:https://www.jb51.cc/wenti/3280184.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐