有点牛逼,滴滴开源的分布式id生成系统
阅读本文大概需要 7 分钟。
来自:网络
简介
tinyid系统架构图
nextId和getNextSegmentId是tinyid-server对外提供的两个http接口
nextId是获取下一个id,当调用nextId时,会传入bizType,每个bizType的id数据是隔离的,生成id会使用该bizType类型生成的IdGenerator。
getNextSegmentId是获取下一个可用号段,tinyid-client会通过此接口来获取可用号段
IdGenerator是id生成的接口
IdGeneratorFactory是生产具体IdGenerator的工厂,每个biz_type生成一个IdGenerator实例。通过工厂,我们可以随时在db中新增biz_type,而不用重启服务
IdGeneratorFactory实际上有两个子类IdGeneratorFactoryServer和IdGeneratorFactoryClient,区别在于,getNextSegmentId的不同,一个是DbGet,一个是HttpGet
CachedIdGenerator则是具体的id生成器对象,持有currentSegmentId和nextSegmentId对象,负责nextId的核心流程。
nextId最终通过AtomicLong.andAndGet(delta)方法产生。
性能与可用性
性能
http方式访问,性能取决于http server的能力,网络传输速度 java-client方式,id为本地生成,号段长度(step)越长,qps越大,如果将号段设置足够大,则qps可达1000w+
可用性
依赖db,当db不可用时,因为server有缓存,所以还可以使用一段时间,如果配置了多个db,则只要有1个db存活,则服务可用 使用tiny-client,只要server有一台存活,则理论上可用,server全挂,因为client有缓存,也可以继续使用一段时间
Tinyid的特性
全局唯一的long型id 趋势递增的id,即不保证下一个id一定比上一个大 非连续性 提供http和java client方式接入 支持批量获取id 支持生成1,3,5,7,9…序列的id 支持多个db的配置,无单点
推荐使用方式
tinyid-server推荐部署到多个机房的多台机器 多机房部署可用性更高,http方式访问需使用方考虑延迟问题 推荐使用tinyid-client来获取id,好处如下: id为本地生成(调用AtomicLong.addAndGet方法),性能大大增加
client对server访问变的低频,减轻了server的压力
因为低频,即便client使用方和server不在一个机房,也无须担心延迟
即便所有server挂掉,因为client预加载了号段,依然可以继续使用一段时间 注:使用tinyid-client方式,如果client机器较多频繁重启,可能会浪费较多的id,这时可以考虑使用http方式
推荐db配置两个或更多: db配置多个时,只要有1个db存活,则服务可用 多db配置,如配置了两个db,则每次新增业务需在两个db中都写入相关数据
tinyid的原理
Id生成系统要点
全局唯一的id:无论怎样都不能重复,这是最基本的要求了 高性能:基础服务尽可能耗时少,如果能够本地生成最好 高可用:虽说很难实现100%的可用性,但是也要无限接近于100%的可用性 简单易用: 能够拿来即用,接入方便,同时在系统设计和实现上要尽可能的简单
Tinyid的实现原理
DB号段算法描述
这里我们增加了biz_type,这个代表业务类型,不同的业务的id隔离
max_id则是上面的end_id了,代表当前最大的可用id
step代表号段的长度,可以根据每个业务的qps来设置一个合理的长度
version是一个乐观锁,每次更新都加上version,能够保证并发更新的正确性 那么我们可以通过如下几个步骤来获取一个可用的号段,
A.查询当前的max_id信息:select id, biz_type, max_id, step, version from tiny_id_info where biz_type='test';
B.计算新的max_id: new_max_id = max_id + step
C.更新DB中的max_id:update tiny_id_info set max_id=#{new_max_id} , verison=version+1 where id=#{id} and max_id=#{max_id} and version=#{version}
D.如果更新成功,则可用号段获取成功,新的可用号段为(max_id, new_max_id]
E.如果更新失败,则号段可能被其他线程获取,回到步骤A,进行重试
号段生成方案的简单架构
简单架构的问题
当id用完时需要访问db加载新的号段,db更新也可能存在version冲突,此时id生成耗时明显增加
db是一个单点,虽然db可以建设主从等高可用架构,但始终是一个单点
使用http方式获取一个id,存在网络开销,性能和可用性都不太好
优化办法如下:
tinyid提供http和tinyid-client两种方式接入 tinyid-server内部缓存两个号段 号段基于db生成,具有原子性 db支持多个 tinyid-server内置easy-router选择db
项目地址
推荐阅读:
成都又一程序员跳楼!一首IT版的《成都》,听哭了所有IT人……
微信扫描二维码,关注我的公众号
朕已阅