分布式ID和分布式锁
一、分布式ID
特点:
- 全局唯一
- 自增
- 高可用
- 高性能
在分布式/分库分表的情况下,需要保证id的自增性和唯一性,所以需要使用分布式ID
实现方式有UUID、雪花算法、Leaf算法
1.1 UUID
长度128位,以32位长度的16进制外加4位连接符的字符串表示(共36位)
例如:123e4567-e89b-12d3-a456-426614174000
优点:
- 简单
- 性能不错
- 本地生成,没有网络消耗
缺点:
- 可读性差
- 存储成本高
- 信息不安全,基于mac地址,容易被攻击
- 非单调递增,容易出现页分裂问题(本质就是B+树分裂重组)
1.2 雪花算法
长度64位,以16位十六进制表示
从左至右依次使用的位数:
1(不使用)+41(时间戳)+10(工作机器id)+12(序列号)
优点:
- 只有64位,节省了存储空间
- 本地生成
- 单调递增(但是不连续),页分裂概率很低
缺点:
- 依赖于时间戳,如果系统时钟发生回拨,可能产生重复的id
1.3 基于Mysql的ID生成
基于mysql实现,将自增id存在某个数据表中,每次插入数据都需要获取并修改一下这个自增id
优点:
- 实现简单
- 自增且连续
缺点:
- 基于mysql实现,并发度不高且负载不高
1.4 基于redis的ID生成
基于redis实现,将自增id存在redis中并使用incr命令修改,原理和mysql类似
优点:
- 实现简单
- 自增连续
- 基于redis实现,负载更高
缺点:
- 要考虑id的持久化
- 如果最大id丢失,很难重新找回
1.5 leaf算法
leaf-segment
在数据库中存储id片段,每次向mysql中请求id片段,例如当前max-id=1000,偏移大小为100,所以每次请求就会请求1001~1100的id到内存中,然后更新数据库,不需要每次请求id都需要访问数据库。
但是如果这些id没有被完全使用,后续将不会再使用。例如:如果上述请求到的1001~1100id,用了几个之后,将内存清除(重启程序),那么下次获取id只能重新请求mysql获取新的id,之前的未使用的id将会浪费。
leaf-snowflake
基于雪花算法的改进,主要是改进了由于时间回拨的重复问题。判断当前时间戳是否小于上一次请求的时间戳,如果小于,则看时间的差值是否在5ms内,如果在5ms内,则等待两倍的时间差的时间后再使用雪花算法获取id,如果大于则报错。
二、分布式锁
实现原理:使用一些公共组件模拟锁的获取
redis、mysql的分布式锁的原理都是在其内部加上一条数据,表示上锁,如果添加成功就表示成功获取锁,失败就是没有获取到锁,释放锁就是删除数据。
- 轮询获取锁:mysql、redis
- 监听删除事件(监听锁(数据)删除的事件)锁:etcd、zookeeper
2.1 基于mysql的分布式锁
缺点:
- 数据库是单点的,可用性不高
- 操作磁盘缓慢
- 无法设置过期时间,容易产生死锁
2.2 基于redis的分布式锁
set key value nx ex 过期时间
看门狗机制
红锁
2.3 基于etcd的分布式锁
ETCD介绍:
Lease机制:
etcd 可以为存储的 key-value 对设置租约,当租约到期,key-value 将失效并被删除,同时也支持续约,通过客户端可以在租约到期之前进行续约, 来避免 key-value 对过期失效。
Revision机制:
每个key带有一个Revision属性值,etcd每进行一次事务对应的全局Revision值都会+1,因此每个key对应的Revision属性值都是全局唯一的,通过比较Revision的大小就可以知道进行写操作的顺序。
prefix机制:
可以根据前缀获得该前缀目录下所有的key及其对应的属性值
watch机制:
当被 监听的 key 或范围发生变化,客户端将收到通知
实现:
Lease机制设置锁的过期时间,存入数据,获取revision,判断获取的revision号是否是足校的,如果不是最小的,就监听小于revision的最大revision数据的删除事件
2.4 zookeeper分布式锁
持久节点
持久顺序节点
临时节点
临时顺序节点
实现:
基于临时顺序节点,创建一个临时顺序节点,检查自身是否是最小的节点,如果不是就监听前一个节点的删除事件,当前一个节点删除的时候就会收到通知。
性能 | mysql < zookeeper/etcd < redis |
---|---|
可靠性 | mysql < redis < zookeeper/etcd |
Redisson的Watch Dog机制
-
如果用户指定过期时间,就不会有看门狗机制
-
如果用户没有指定,则会有看门狗机制,但是如果线程拿到锁之后,一直执行(假设无限时间),则锁永远不会过期
-
看门狗设置续期阙值不能太小,太小会由于网络延迟导致续期时锁已经被删除。