今天是2020-12-23。
最后两节就看看算法,也算是不用动手了,就是烧脑。
一。分布式系统全局唯一id的生成规则要求
1.全局唯一:不能出现重复的id
2.趋势递增:
3.单调递增:保证全局情况下,生成的id一定大于上一个id
4.信息安全:如果id连续,可能会被轻易的获取信息,所以要让id无规则/不规则,还要满足第三条
5.含时间戳:可以方便了解id的生成时间
二。分布式系统全局唯一id的可用性要求
1.高可用:发一个获取分布式全局id的请求,服务器要保证百分之99的情况下能创建并响应给我需要的id
2.低延迟:服务器响应的速度要非常快,流量大的系统不允许高延迟
3.高qps:要承担的住同一时刻大数量的流量
三。通常会想到的方案
- UUID,在这个地方的不足,存入数据库时的性能比较差:
1.分布式id一般会作为主键,无法预测生成顺序,就不能以有序数字来存储。而且mysql推荐主键尽量短,但是UUID太长
2.分布式id作为主键,就会有主键索引。mysql的索引使用b+树实现,每一次存入新的UUID,都会修改底层的B+树,但UUID是无序的,这个修改的成本就会很大。存入时是无序的,不但会导致中间节点分裂,也会创造出很多不饱和的节点,大大降低性能
2.数据库自增主键
1.单机时使用replace into机制:插入一条数据,如果表中唯一索引的值遇到冲突,则删除旧数据
2.在集群时,mysql很难进行水平扩展,mysql集群中不同的服务器生成的id的初始值是要不同的,如果服务器太多,就很难扩容
3.集群时,每次获取id都要去数据库进行读写操作,非常影响性能,这是不符合低延迟、高qps的要求的
3.redis生成:
1.redis天生单线程,响应速度会非常快,而且可以用原子操作incr和incrby来实现id增长
2.涉及到集群时,也要设置每台redis服务器的初始值和增长区间,确实也可以获得全局唯一的分布式id,redis不同的服务器设置不同的起始值就比mysql不同服务器要去扩容方便多了。
3.但为了生成分布式id,却要维护一个redis集群,为了保证不出现单点故障,可能要启用哨兵模式监控主服务器,总的来说性价比有点低,太麻烦了。
四。snowflake雪花算法
1.是twitter的开源算法
2.生成的id是Long型的64bit大小的整数
3.在分布式系统内,生成的id不会碰撞,且按时间递增,且生成的效率非常高
4.结果解析:
1.结果是64bit,1bit符号位+41bit时间戳+10bit工作进程位+12bit序列号位
2.1bit符号位:生成的一般是正整数,基本不使用,固定为0
3.41bit时间戳:如果41位都是1,那么就是2的41次方-1,大约是69年
4.10bit工作进程位:用来记录工作机器的id,由5位datacenter和5位workid组成。每5位可表达的范围是0-31,即2的5次方-1
5.12bit序列号位:用来区分同一机器同一毫秒数内产生的不同id,最多可记录4095个不同的id,也就是2的12次方-1
5.优点:id呈递增趋势,不依赖第三方机器,本身可以作为一个服务部署,稳定性强,性能高
6.缺点:依赖机器时钟,如果时钟回调会出现问题。而且不同服务器的机器时钟可能不一样,无法做到全局都是严格递增
7.补充,国内有完善的版本:百度的UidGenerator和美团的Leaf。
五。完结感言
25号一看才发现当时写完忘了发布了,历时19天看完了这个系列视频,中间还是有几天懈怠了吧。其实一路看下来也发现很多东西真的阳哥也没办法讲的太深,所以还得不断地学习,目前这个状态对于我自己来说,应该叫学习了cloud基础,又得添加一个学习目标:cloud进阶。在实习之前断断续续的学完cloud以后,接下来的24号到25号的三点,都没有再想学别的,下周一就要实习了,毕设也要开始了,哪怕很难从我十几个还要学的东西去挑一个开始,也需要为实习去做准备了。回头看看,这一段时间也是很神奇:看康师傅的java700集自己总结个49页笔记,上学9-11月份,总结了1740个主题的思维导图,这19天下来又总结了19篇博客,接下来估计就在博客写学习总结了,导图还是有点不好发挥,继续加油吧。