全局id生成器試用之Leaf

數據量上來後,單庫單表承受不住的時候,我們就需要引入分庫分表。 但是分庫分表後,主鍵id就不能依賴於MySQL,需要從外部去獲取id。


目前我們生產環境在用的DBLE作爲中分庫分表中間件, 其自帶了類似snowflake方案的全局id生成器,也可以基於數據庫來實現。


但是,在一個大點的公司裏面, 全局id 是一個用處很廣泛的服務,通常會獨立作爲一個公共服務對外提供。


這裏我們就以 美團點評出的 Leaf爲例,看下它的效果。


相關文檔:

https://tech.meituan.com/2019/03/07/open-source-project-leaf.html

https://tech.meituan.com/2017/04/21/mt-leaf.html

https://blog.csdn.net/bskfnvjtlyzmv867/article/details/90175306  源碼詳解


官方的2篇文檔,介紹的很詳細了,我們就不囉嗦了。



下面的演示,是基於數據庫做id分發 (數據庫的SLA可以使用MHA、pxc或mgr來保證)



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/tid


5 其它

號段模式自帶了個監控界面:   

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都用光後,就會報錯了:

image.png


只要我們的MySQL數據庫故障切換的時候不要太久,並且配合設置不同biz_tag以不同大小的step,通不會對對leaf服務造成影響。



下面是雙buffer在web界面上的體現:

image.png



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章