本文来自官方文档的简单总结,非原创!!!
原始方案每次获取ID都要读写数据库,数据库压力比较大。
每次获取一个号段的值(step决定大小),用完之后再去数据库获取新的号段,很大减轻数据库的压力。
各个业务不同的需求用biz_tag字段来区分。
如果以后因为性能等原因需要分库分表,只需要对biz_tag分库分表。
+-------------+--------------+------+-----+-------------------+-----------------------------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+-------------------+-----------------------------+ | biz_tag | varchar(128) | NO | PRI | | | | max_id | bigint(20) | NO | | 1 | | | step | int(11) | NO | | NULL | | | desc | varchar(256) | YES | | NULL | | | update_time | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP | +-------------+--------------+------+-----+-------------------+-----------------------------+
biz_tag:区分业务。
max_id:表示该biz_tag目前所被分配的ID号段的最大值。
step:表示每次分配的号段长度。
原来获取ID每次都需要写数据库,现在只需要把step设置得足够大,比如1000。
那么只有当1000个号被消耗完了之后才会去重新读写一次数据库。
Begin UPDATE table SET max_id=max_id+step WHERE biz_tag=xxx SELECT tag, max_id, step FROM table WHERE biz_tag=xxx Commit
针对第二个缺点,Leaf做了双buffer优化。
希望DB取号段的过程能够做到无阻塞,即当号段消费到某个阈值时就异步的把下一个号段加载到内存中。
而不是等到号段用尽的时候才去更新号段,这样做可以很大程度上的降低突刺问题。
每个biz-tag都有消费速度监控,推荐segment长度设置为服务高峰期发号QPS的600倍(10分钟)。
这样即使DB宕机,Leaf仍能持续发号10-20分钟不受影响。
针对"DB可用性"的问题,采用一主两从且分机房部署,Master和Slave之间采用半同步方式同步数据。
同时使用DBProxy数据库中间件做主从切换。
这种异步模式在非常极端情况下仍然会造成数据不一致的情况,但是出现的概率非常小。
如果系统要保证100%的数据强一致,可以选择使用“类Paxos算法”实现的强一致MySQL方案,如MySQL 5.7的Group Replication。
但是运维成本和精力都会相应的增加,根据实际情况选型即可。
同时Leaf服务分IDC部署,内部的服务化框架是“MTthrift RPC”。
服务调用的时候,根据负载均衡算法会优先调用同机房的Leaf服务。
在该IDC内Leaf服务不可用的时候才会选择其他机房的Leaf服务。
同时服务治理平台OCTO还提供了针对服务的过载保护、一键截流、动态流量分配等对服务的保护措施。