Dubbo学习系列之七(分布式订单ID方案)
既然选择,就注定风雨兼程!
开始吧!
准备:Idea201902/JDK11/ZK3.5.5/Gradle5.4.1/RabbitMQ3.7.13/Mysql8.0.11/Lombok0.26/Erlang21.2/postman7.5.0
难度:新手--战士--老兵--大师
目标:1,使用“雪花算法”生成订单ID 2,使用集中式Redis生成订单明细ID,3.Logback+slf4j打印日志
步骤:1.项目架构及代码基础设施,见往期文章。2.整体思路:其实ID的生成有很多种方案,如UUID,DB自增id,那分布式环境下有何方案呢?UUID也可以,但无规律;DB生成法,间隔初始值加步长,水平扩展差;雪花算法,服务器间时间同步是个问题,Redis集中式生成,容易单点瓶颈。总结而言,各有千秋,一是独立式,每个使用者自己生成,二是中心式,ID集中产生再分发。今天我们来看看典型代表: 雪花算法和Redis集中式。3.先说"雪花算法",理解也简单,“世界上没有一片雪花是相同的”顾名思义,雪花算法即是多维度组合,生成一个ID值,且这个值“趋势递增”,其核心构成如下图:

64bit,第一位0固定,二进制符号位,41bit时间戳,注意是当前与初始值相减的值,10bit工作机器id,12bit序列号,毫秒内的计数,其中工作机器id可预先人工指定,最后64位刚好转成Long类型即可。
4.算法生成类,放公共模块,com.biao.mall.common.util.SnowFlake
先来个整体的代码,包含了几个内部方法:

再来分析一下,

重点看下最大值,使用对-1左移位算法,(二进制右边补0),再按位取反,举例:最多2位,
~(-1L<<2)-->11111111-->11111100-->00000011-->3,实际上这里,就是(2的n次方-1),因移位算法是效率最高的,因此采用。
private final static long MAX_DATAC_ENTER_ID = ~(-1L << DATACENTER_BIT);
private final static long MAX_WORK_ID= ~(-1L << MACHINE_BIT);
private final static long MAX_SEQUENCE = ~(-1L << SEQUENCE_BIT);
构造函数中判断下数据中心id和主机id是否合法,

5.算法核心部分,nextId()方法,注意这是个同步方法,线程安全的:

A.先取得当前主机的毫秒,判断下是否小于上个时间戳,这个很重要!因为如果时间回拨,会导致可能的ID重复,因此当遇到时间回拨的情况,可以考虑使用备份的主机ID,这里是直接抛异常了。
B.如果取ID并发非常高,导致时间间隔很小,在同一毫秒内,则序列号自增并和最大序列号"按位与",这样的目的就是如果序列号达到最大,+1再按位与,就会等于0,(假设2位最大值加1:011+001=100,再100 & 011=000,然后只有2位就成0了)
C. 如果同一毫秒内序列号达到最大归为0,就使用getNextMill(),无限循环直到获得下个毫秒数
D.最后生成id就是时间戳差值,移位再按位或其他部分的数值,
6.再看Redis方案,这个主要是利用Redis速度快的特点,并可以使用Redis集群,就可确保速度和可用性,集中式的好处即统一生产,易控制,但分发受网络波动影响。具体位置在:com.biao.mall.common.util.RedisUitl7.分析重点:类里写了两个生成方式,第一个doGetId()是个简单生成法,直接使用对一个key做自增操作,每次递增一个,但坏处明显,容易暴露一天的订单量!数鸭子的游戏。

这里使用的是redisAPI的redisTemplate,其有操作如下,即对redis的五种数据类型都有对应的封装方法。

还有一个思路是先缓存,再取值,过程是:先生成一定量的顺序数,打乱顺序,再分成若干段,循环存入redis,取值时,根据全局计数器进行检索取值,

以下为分段存储,每个段都有个keyId。这里为啥,做分段?主要是存取效率问题,显然从一小段中检索数据要快于直接从一个大的List中检索快。

取乱序值方法getShuffleId:因为这个是个开箱即用的静态方法,必须保证首次使用时,初始化计数器,并执行分段存储操作,而应用重启,不重复这个操作,故可以先判断计数器是否已存在。取值是先找到分段的list的key,再找到偏移量index:

7.测试一下,我写了个controller:com.biao.mall.business.controller.MsgProducerController

启动Redis-->zk-->business:
可以看到,前面两图就是顺序的,而后面的两图则是乱序的。

8.项目地址:day10
https://github.com/xiexiaobiao/dubbo-project.git
后记:
1.关于服务间通信:内部服务间通信宜使用私有通信,如RPC,Netty等,效率高,对外使用Restful,兼容性好,因此,项目代码编号day09成为了一个临时版,其实现了MQ独立部署,Restful对内通信的模式,但技术上不可取。
2.redis生产中不会使用单点,常用的是集群式,如三主三从集群,但从使用者角度,有JedisCluster,如操作redisTemplate类似,逻辑上是操作一个,不必考虑后台实现与具体的物理分库存储。
3.看代码,多思考,才有收获,此文中有关于二进制的操作,试问(1L<<-1)可否?为啥使用二进制操作呢?
4.分布式Id方案,有很多,各有特点,生搬硬套行不通,必须根据业务特点取舍和改造。
5.之前在做MQ解析时遇到,一定小心!注意jsonString传输:以下String将发生JSON.parse()错误。"{\"orderId\":\"362951082266333184\",\"URL\":\"http://localhost:8085/delivery/one\"}",去掉json中的转义字符,可使用StringEscapeUtils.unescapeJava(jsonString)
往期文章导航:
Dubbo学习系列之四(MybaitsPlus+Druid使用)
我的微信公众号,只写原创文章!

Dubbo学习系列之七(分布式订单ID方案)的更多相关文章
- Dubbo学习系列之八(分布式事务之MQ方案)
自从小王玩起了微服务,发现微服务果然很强大,好处真是太多,心中暗喜,然而,却也遇到了分布式中最棘手的问题:分布式事务.小王遍访各路神仙,也无个完美开源解决方案,当然,也有些实际可行的手法,虽不算完美, ...
- Dubbo学习系列之九(Shiro+JWT权限管理)
村长让小王给村里各系统来一套SSO方案做整合,隔壁的陈家村流行使用Session+认证中心方法,但小王想尝试点新鲜的,于是想到了JWT方案,那JWT是啥呢?JavaWebToken简称JWT,就是一个 ...
- Dubbo学习系列之十(Sentinel之限流与降级)
各位看官,先提个问题,如果让你设计一套秒杀系统,核心要点是啥???我认为有三点:缓存.限流和分离.想当年12306大面积崩溃,还有如今的微博整体宕机情况,感觉就是限流降级没做好,"用有限的资 ...
- Dubbo学习系列之十五(Seata分布式事务方案TCC模式)
上篇的续集. 工具: Idea201902/JDK11/Gradle5.6.2/Mysql8.0.11/Lombok0.27/Postman7.5.0/SpringBoot2.1.9/Nacos1.1 ...
- Dubbo学习系列之十六(ELK海量日志分析框架)
外卖公司如何匹配骑手和订单?淘宝如何进行商品推荐?或者读者兴趣匹配?还有海量数据存储搜索.实时日志分析.应用程序监控等场景,Elasticsearch或许可以提供一些思路,作为业界最具影响力的海量搜索 ...
- Dubbo学习系列之十一(Dashboard+Nacos规则推送)
中国武术,门派林立,都是号称多少代的XXX传人,结果在面对现代武术时,经常被KO秒杀,为啥,光靠宣传和口号撑门面,终究是靠不住,必须得有真货 ,得经得住考验,所以不能只说Sentinel有多好,也得给 ...
- Dubbo学习系列之十三(Mycat数据库代理)
软件界有只猫,不用我说,各位看官肯定知道是哪只,那就是大名鼎鼎的Tomcat,现在又来了一只猫,据说是位东方萌妹子,暂且认作Tom猫的表妹,本来叫OpencloudDB,后又改名为Mycat,或许Ca ...
- Dubbo学习系列之十二(Quartz任务调度)
Quartz词义为"石英"水晶,然后聪明的人类利用它发明了石英手表,因石英晶体在受到电流影响时,它会产生规律的振动,于是,这种时间上的规律,也被应用到了软件界,来命名了一款任务调度 ...
- 大数据学习系列之七 ----- Hadoop+Spark+Zookeeper+HBase+Hive集群搭建 图文详解
引言 在之前的大数据学习系列中,搭建了Hadoop+Spark+HBase+Hive 环境以及一些测试.其实要说的话,我开始学习大数据的时候,搭建的就是集群,并不是单机模式和伪分布式.至于为什么先写单 ...
随机推荐
- [增强for循环] 格式
比如:
- [RAM] FPGA的学习笔记——RAM
1.RAM——随机存取存储器, 分为SRAM和DRAM. SRAM:存和取得速度快,操作简单.然而,成本高,很难做到很大.FPGA的片内存储器,就是一种SRAM,用来存放程序,以及程序执行过程中,产生 ...
- 微信web协议,群成员唯一uin,获取群成员唯一标识
群成员唯一标识获取接口 全网最新,支持调试测试.觉得OK再付款! 800元出售源码 不讲价 联系QQ:2052404477
- java编程思想第四版第十八章总结
一.概述 如何学习java I/O 学习I/O类库 学习I/O发展史,为什么要学习发展史呢? 因为,如果缺乏发展史,我们就会对什么时候使用哪个类,以及什么时候不该使用它们而感到迷惑. 了解nio 二. ...
- 【SpringBoot | Redis】SpringBoot整合Redis
SpringBoot整合Redis 1. pom.xml中引入Redis相关包 请注意,这里我们排除了lettuce驱动,采用了jedis驱动 <!-- redis的依赖 --> < ...
- ubuntu 16.04上源码编译glog和gflags 编写glog-config.cmake和gflags-config.cmake | compile glog and glags on ubuntu 16.04
本文首发于个人博客https://kezunlin.me/post/977f5125/,欢迎阅读! compile glog and glags on ubuntu 16.04 Series comp ...
- Code Helper占用大量CPU和内存
项目架构: React+TS+DVA 设备及软件: 设备:Mac 软件:VSCode 场景: 在Mac中使用VSCode运行时发现项目编译非常卡顿,时间长达五六分钟以上,并且项目启动后访问页面,页面也 ...
- javaScript——label语句
第一次看见label语句是这样一个场景: function foo() {x: 1} 当时十分疑惑,为什么不报错呢?对象可以这样写? 后来知道这个是label语句,一般配合break和continue ...
- 【集训Day1 测试】奇怪数
奇怪数(odometer) [题目描述] 一个正整数Z是奇怪数,当且仅当满足的条件是:Z的所有数字中,只有一个数字不同于其他数字.例如:33323.110 都是奇怪数,而 9779.5555 都不是奇 ...
- Linux下为知笔记和蚂蚁笔记测评,推荐蚂蚁笔记!(非广告)
本人由于学习Linux,需要一款可以在Linux平台下可以运行的一款软件,了解到为知笔记之笔记(下文以W代替)和蚂蚁笔记(下文以M代替)比较出名,由于某云和某象笔记在linux平台下没有对应的软件,所 ...