資料庫中介軟體MyCat之主鍵值生成方式詳解
阿新 • • 發佈:2022-12-07
開啟新的專題【資料庫中介軟體】第7節,一起開啟資料庫中介軟體的學習,上節回顧:本機windows系統啟動mycat,訪問3臺虛擬機器,演示mycat的11種分片策略演示,防止入坑。本節就演示上節提到的主鍵6種生成方式。
(一)主鍵值生成方式
- ① 介紹
在實現分庫分表的情況下,原來是一張表就分到多個庫上面和多個表上面,各個表都有自增,無法保證資料庫自增主鍵自增主鍵的全域性唯一。為此,MyCat 提供了全域性sequence,並且提供了包含本地配置和資料庫配置等多種實現方式。CREATETABLE t_customer( idBIGINT PRIMARY KEY, namevarchar(100) notnull, province intnotnull ); <tablename="t_customer"primaryKey="id"autoIncrement="true"dataNode="dn1,dn2,dn3"rule="sharding-by-province" />
- ② 本地檔案方式
原理:此方式MyCAT 將sequence 配置到檔案中,當使用到sequence 中的配置後,MyCAT 會更新 conf中的sequence_conf.properties 檔案中sequence 當前的值。
配置方式:
1.在sequence_conf.properties 檔案中做如下配置
HISIDS 歷史ID
MIXID 最小ID
MAXID 最大ID
CURID 當前IDGLOBAL.HISIDS= GLOBAL.MINID=1001GLOBAL.MAXID=1000000000GLOBAL.CURID=1000
其中HISIDS 表示使用過的歷史分段(一般無特殊需要可不配置),MINID 表示最小ID 值,MAXID 表示最大 ID 值,CURID 表示當前ID 值。
2.server.xml 中配置
注:sequnceHandlerType 需要配置為0,表示使用本地檔案方式。<system><propertyname="sequnceHandlerType">0</property></system>
使用示例
缺點:當MyCAT 重新發布後,配置檔案中的sequence 會恢復到初始值。 優點:本地載入,讀取速度較快。為表配置主鍵自增值的序列。如果需要重啟,需要先將這個檔案進行拷貝出來,修改後,在拷貝到這個位置。insertinto table1(id,name) values(nextvaluefor MYCATSEQ_GLOBAL,‘test’);
為表配置主鍵自增值的序列:
規則:在sequence_conf.properties 中配置以表名為名的序列。T_COMPANY.CURID=501 T_COMPANY.MINID=1 T_COMPANY.MAXID=1000000000
就可以使用了。<tablename="t_company"primaryKey="id"autoIncrement="true"dataNode="dn1,dn2,dn3"rule="range-sharding-by-members-count" /> INSERTINTO t_company(name,members) VALUES('company06',200); select * from t_company;
- ③ 資料庫方式
在資料庫中建立一張表,存放sequence 名稱(name),sequence 當前值(current_value),步長(increment int型別,每次讀取多少個sequence)等資訊。
Sequence 獲取步驟
- 當初次使用該sequence 時,根據傳入的sequence 名稱,從資料庫這張表中讀取
- current_value,和 increment 到MyCat 中,並將資料庫中的current_value 設定為原
- current_value 值+increment 值。
- MyCat 將讀取到current_value+increment 作為本次要使用的sequence 值,下次使用
- 時,自動加1,當 使用increment 次後,執行步驟1)相同的操作。
MyCat 負責維護這張表,用到哪些sequence,只需要在這張表中插入一條記錄即可。若某次讀取的 sequence 沒有用完,系統就停掉了,則這次讀取的sequence 剩餘值不會再使用。
注:sequnceHandlerType 需要配置為1,表示使用資料庫方式生成sequence。<system><propertyname="sequnceHandlerType">1</property></system>
資料庫配置:
- 建立MYCAT_SEQUENCE 表
- 建立相關function
注意:MYCAT_SEQUENCE 表和以上的3 個function,需要放在同一個節點上。function 請直接在具體節點的資料庫上執行,如果執行的時候報: you might want to use the less safe log_bin_trust_function_creators variable
需要對資料庫做如下設定: windows 下my.ini[mysqld]加上
log_bin_trust_function_creators=1 linux 下/etc/my.cnf 下my.ini[mysqld]加上
log_bin_trust_function_creators=1 修改完後,即可在mysql 資料庫中執行上面的函式。
- sequence_db_conf.properties 相關配置,指定sequence 相關配置在哪個節點上:
使用示例:
insertinto table1(id,name) values(nextvaluefor MYCATSEQ_GLOBAL,'test');配置表的主鍵自增使用序列
1 在序列定義表中增加名字為表名的序列
INSERTINTO MYCAT_SEQUENCE(name,current_value,increment) VALUES ('T_COMPANY', 1,100);2 在sequence_db_conf.properties中增加表的序列配置
T_COMPANY=dn13 主鍵自增就可以使用了
<tablename="t_company"primaryKey="id"autoIncrement="true"dataNode="dn1,dn2,dn3"rule="range-sharding-by-members-count" /> INSERTINTO t_company(name,members) VALUES('company08',200); select * from t_company;- ④ 本地時間戳方式
原理:
ID= 64 位二進位制:42(毫秒)+5(機器ID)+5(業務編碼)+12(重複累加)。
換算成十進位制為18 位數的long 型別,每毫秒可以併發12 位二進位制的累加。
使用方式:
1.配置server.xml
<propertyname="sequnceHandlerType">2</property>2.在mycat 下配置:sequence_time_conf.properties
WORKID=0-31 任意整數 表示機器id(或mycat例項id)
DATAACENTERID=0-31 任意整數 業務編碼
多個mycat 節點下每個mycat 配置的WORKID,DATAACENTERID 不同,組成唯一標識,總共支援32*32=1024 種組合。
ID 示例:56763083475511 。
主鍵自增配置<tablename="t_company"primaryKey="id"autoIncrement="true"dataNode="dn1,dn2,dn3"rule="range-sharding-by-members-count" /> INSERTINTO t_company(name,members) VALUES('company09',200); select * from t_company;
- ⑤ 分散式ZK ID生成器
server.xml# system 中新增 <propertyname="sequnceHandlerType">3</property>
配置
1.Zk 的連線資訊統一在myid.properties 的zkURL 屬性中配置。此只需關注zkURL。loadZk=false zkURL=127.0.0.1:2181 clusterId=mycat-cluster-1 myid=mycat_fz_01 clusterSize=3 clusterNodes=mycat_fz_01,mycat_fz_02,mycat_fz_04 #server booster ; booster install on db same server,will reset all minCon to 2 type=server boosterDataHosts=dataHost1
基於ZK 與本地配置的分散式ID 生成器,ID 結構:long 64 位,ID 最大可佔63 位:
- |current time millis(微秒時間戳38 位,可以使用17 年)|clusterId(機房或者ZKid,通過配置檔案配置5 位)|instanceId(例項ID,可以通過ZK 或者配置檔案獲取,5
- 位)|threadId(執行緒ID,9 位) |increment(自增,6 位)
- 一共63 位,可以承受單機房單機器單執行緒1000*(2^6)=640000 的併發。
- 無悲觀鎖,無強競爭,吞吐量更高
- 配置檔案:sequence_distributed_conf.properties,只要配置裡面:INSTANCEID=ZK 就是從ZK 上獲取 InstanceID。(可以通過ZK 獲取叢集(機房)唯一InstanceID,也可以通過配置檔案配置InstanceID)
測試<tablename="t_company"primaryKey="id"autoIncrement="true"dataNode="dn1,dn2,dn3"rule="range-sharding-by-members-count" /> INSERTINTO t_company(name,members) VALUES('company10',200); select * from t_company;
- ⑥ ZK 遞增的方式
server.xml# system 中新增 <propertyname="sequnceHandlerType">4</property>
Zk 的連線資訊統一在myid.properties 的zkURL 屬性中配置。
配置:
配置檔案:sequence_conf.properties 只要配置好ZK 地址和表名的如下屬性
- TABLE.MINID 某執行緒當前區間內最小值
- TABLE.MAXID 某執行緒當前區間內最大值
- TABLE.CURID 某執行緒當前區間內當前值
檔案配置的MAXID 以及MINID 決定每次取得區間,這個對於每個執行緒或者程序都有效。檔案中的這三個屬性配置只對第一個程序的第一個執行緒有效,其他執行緒和程序會動態讀取ZK。
測試<tablename="t_company"primaryKey="id"autoIncrement="true"dataNode="dn1,dn2,dn3"rule="range-sharding-by-members-count" /> INSERTINTO t_company(name,members) VALUES('company12',200); select * from t_company;
- ⑦ last_insert_id() 問題
我們配置分片表主鍵自增。<tablename="t_company"primaryKey="id"autoIncrement="true"dataNode="dn1,dn2,dn3"rule="range-sharding-by-members-count" />
如需通過 select last_insert_id() 來獲得自增主鍵值,則表定義中主鍵列需是自增的
AUTO_INCREMENTCREATETABLE t_company( idBIGINT PRIMARY KEY AUTO_INCREMENT, namevarchar(100) notnull, members intnotnull );
如果沒有指定 AUTO_INCREMENT,則select last_insert_id() 獲取不到剛插入資料的主鍵值。CREATETABLE t_company( idBIGINT PRIMARY KEY, namevarchar(100) notnull, members intnotnull );
Mybatis 中新增記錄後獲取last_insert_id 的示例<insertid="insert"parameterType="com.study.mike.user.model.User"> insert into t_user (user_name,login_name,login_pwd,role_id) values(#{userName},#{loginName},#{loginPwd},#{roleId}) <selectKeyresultType="java.lang.Long"order="AFTER"keyProperty="id"> select last_insert_id() as id </selectKey></insert>
PS:這就是myCat相關分庫分表先關的內容,建議不選擇檔案的方式,選擇資料庫的方式或者是zk的方式來確定主鍵的生成,保證唯一性