分布式ID-入门了解

分布式ID-入门了解

1. 概念:

在分布式系统中,经常需要对大量的数据、消息、http请求等进行唯一标识,就需要不能出现的ID。
互联网应用中,某个表可能要占用很大的物理存储空间,为了解决该问题,使用数据库分片技术。将一个数据库进行拆分,通过数据库中间件连接。
如果数据库中该表选用ID自增策略,则可能产生重复的ID,此时应该使用分布式ID生成策略来生成ID。
	例如:比如下订单需求,因数据库订单表已经分片,若用主键自增,分片后的各个表会产生重复ID。所以这个系统需要满足以下需求:
		全局唯一:不能出现重复ID。
		高可用:ID生成系统是基础系统,被许多关键系统调用,一旦宕机,会造成严重影响。

2.解决方式:

1.UUID(本地生成32位的ID,不需要进行远程调用,时延低,性能高;ID过长,没有排序)
2.Flicker方案(采用了MySQL自增长ID的机制,可靠性高,有序;系统扩容困难,数据库压力大)
3.TDDL序列生成方式(阿里的分库分表中间件,有全局数据库ID的生成方式;强依赖数据库,数据库异常时整个系统不可用)
4.Redis(可产生自增序号;主键产生需强依赖Redis)
5.Oracle(可产生与表无关的序列;只有Oracle数据库才能使用)
6.Snowflake算法(有序,性能高,可调整bit位划分;
			依赖机器时钟,如果机器时钟回拨,会导致重复ID生成。
			在单机上是递增的,但是由于涉及到分布式环境,每台机器上的时钟不可能完全同步,有时候会出现不是全
			局递增的情况。)

***推荐使用雪花算法,时钟问题可百度解决!!!	
主要原因:
	业务需求:业务要求生成的ID要有递增趋势,全局唯一,并且为数字。
	系统考虑:第三种方案性能高,稳定性高,对外部资源依赖少。
	依据实际业务需求和系统规划,对算法进行局部调整,可使用 发号器snowflake方案。	

3.Snowflake算法:

	开源的twitter( 非官方中文惯称:推特。是国外的一个网站,是一个社交网络及微博客服务)的snowflake算法。
	* <p>名称:IdWorker.java</p>
	* <p>描述:分布式自增长ID</p>
	* <pre>
	*     Twitter的 Snowflake JAVA实现方案
	* </pre>
	* 核心代码为其IdWorker这个类实现,其原理结构如下,我分别用一个0表示一位,用—分割开部分的作用:
	* 1||0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
	* 在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,
	* 然后5位datacenter(数据中心)标识位,5位机器(也叫进程)ID(并不算标识符,实际是为线程标识),
	* 然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
	* 这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),
	* 并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。
	* 64位二进制ID (42(毫秒)+5(机器ID)+5(业务编码)+12(重复累加序列号))-->生成后会转为十进制的long类型整数
【使用】:
	(1)工具类IdWorker.java拷贝到common工具类工程;
	(2)在service工程的spring配置文件中添加配置(每个节点的进程和数据数据不能一样,若一样ID可能会重复);
		<bean id="idWorker" class="util.IdWorker">
			<!-- 进程 ID 取值:0~31 -->
			<constructor-arg index="0" value="0"></constructor-arg>
			<!-- 数据中心 ID 取值:0~31 -->
			<constructor-arg index="1" value="0"></constructor-arg>
		</bean>
	(3)生成。
		@Autowired
		private IdWorker idWorker;
		long orderId = idWorker.nextId();
	**直接用:
		IdWorker idWorker = new IdWorker();
		long orderId = idWorker.nextId();

猜你喜欢

转载自blog.csdn.net/qq_24827537/article/details/83472462