全局id生成器試用之Leaf

數據量上來後,單庫單表承受不住的時候,咱們就須要引入分庫分表。 可是分庫分表後,主鍵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/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

相關文章
相關標籤/搜索