數據量上來後,單庫單表承受不住的時候,咱們就須要引入分庫分表。 可是分庫分表後,主鍵id就不能依賴於MySQL,須要從外部去獲取id。html
目前咱們生產環境在用的DBLE做爲中分庫分表中間件, 其自帶了相似snowflake方案的全局id生成器,也能夠基於數據庫來實現。node
可是,在一個大點的公司裏面, 全局id 是一個用處很普遍的服務,一般會獨立做爲一個公共服務對外提供。mysql
這裏咱們就以 美團點評出的 Leaf爲例,看下它的效果。git
相關文檔:github
https://tech.meituan.com/2019/03/07/open-source-project-leaf.htmlweb
https://tech.meituan.com/2017/04/21/mt-leaf.htmlspring
https://blog.csdn.net/bskfnvjtlyzmv867/article/details/90175306 源碼詳解sql
官方的2篇文檔,介紹的很詳細了,咱們就不囉嗦了。數據庫
下面的演示,是基於數據庫作id分發 (數據庫的SLA可使用MHA、pxc或mgr來保證)vim
0 環境
OS版本: CentOS7
node1 IP: 192.168.20.10
node2 IP: 192.168.20.17
MySQL地址: 192.168.20.10
1 建立數據庫表等
CREATE DATABASE leaf ; use leaf ; CREATE TABLE `leaf_alloc` ( `biz_tag` varchar(128) NOT NULL DEFAULT '', -- your biz unique name `max_id` bigint(20) NOT NULL DEFAULT '1', `step` int(11) NOT NULL, `description` varchar(256) DEFAULT NULL, `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`biz_tag`) ) ENGINE=InnoDB; -- 插入幾條須要分發id的服務的標識(我這裏在默認的基礎上,加了 卡券id、帖子id 這2個例子) insert into leaf_alloc(biz_tag, max_id, step, description) values('leaf-segment-test', 1, 2000, 'Test leaf Segment Mode Get Id'); insert into leaf_alloc(biz_tag, max_id, step, description) values('coupon', 1, 2000, 'Get coupon Id'); insert into leaf_alloc(biz_tag, max_id, step, description) values('tid', 1, 1000, 'Get tiezi id'); select * from leaf_alloc ; +-------------------+--------+------+-------------------------------+---------------------+ | biz_tag | max_id | step | description | update_time | +-------------------+--------+------+-------------------------------+---------------------+ | coupon | 1 | 2000 | Get coupon Id | 2019-10-12 17:47:23 | | leaf-segment-test | 1 | 2000 | Test leaf Segment Mode Get Id | 2019-10-12 17:47:00 | | tid | 1 | 1000 | Get tiezi id | 2019-10-12 17:48:21 | +-------------------+--------+------+-------------------------------+---------------------+ 3 rows in set (0.001 sec) -- 建立獨立的數據庫帳號 create user leaf@'%' identified by 'leaf1234'; grant select,update,delete,insert on leaf.* to leaf@'%';
2 編譯leaf-server
注意:須要在node1和node2上單獨執行編譯和啓動的操做,編譯+啓動 依賴到 maven 和 oracle-jdk
cd /usr/local/ git clone https://github.com/Meituan-Dianping/Leaf.git cd leaf mvn clean install -DskipTests cd leaf-server
vim leaf-server/src/main/resources/leaf.properties 修改配置文件中數據庫的鏈接方式
leaf.name=com.sankuai.leaf.opensource.test leaf.segment.enable=true leaf.jdbc.url=jdbc:mysql://192.168.20.10:3306/leaf?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8 leaf.jdbc.username=leaf leaf.jdbc.password=leaf1234 leaf.snowflake.enable=false #leaf.snowflake.zk.address= #leaf.snowflake.port=
3 啓動leaf-server:
cd /usr/local/leaf/leaf-server mvn spring-boot:run
4 測試
測試我上面插入的3個biz_tag的發號器狀況:
curl http://192.168.20.10:8080/api/segment/get/leaf-segment-test
curl http://192.168.20.10:8080/api/segment/get/coupon
curl
http://192.168.20.10:8080/api/segment/get/tid5 其它
號段模式自帶了個監控界面:
http://192.168.20.10:8080/cache測試id的生成效果:
for i in {1..2000}; do curl http://192.168.20.17:8080/api/segment/get/coupon; done for i in {1..2000}; do curl http://192.168.20.10:8080/api/segment/get/coupon; done
而後,咱們在for循環獲取id的時候,人爲的把MySQL關閉掉,能夠看到以下的,能夠看到剛開始leaf由於號段+雙buffer的存在,能夠繼續發號,可是當預分配的id都用光後,就會報錯了:
只要咱們的MySQL數據庫故障切換的時候不要過久,而且配合設置不一樣biz_tag以不一樣大小的step,通不會對對leaf服務形成影響。
下面是雙buffer在web界面上的體現: