簡(jiǎn)介
隨著微服務(wù)框架的逐步應(yīng)用,分布式ID生成策略要支持高并發(fā)搁进、有序性浪感、易讀性。常用方案有UUID饼问、GUID影兽、Redis、MongoDB等莱革,本次只提供數(shù)據(jù)庫(kù)生成方式峻堰。作為平臺(tái)框架基于適配原則提供數(shù)據(jù)庫(kù)層面的選擇,以下為具體的設(shè)計(jì)盅视。
- 可適用于ID持續(xù)增長(zhǎng)捐名,固定編碼長(zhǎng)度,不足補(bǔ)零闹击。
- 可適用于每天镶蹋、每月、每年階段性的清零自增長(zhǎng)赏半。
- 可指定編碼的前綴贺归、后綴。
- 階段性的清零操作無需定時(shí)任務(wù)断箫。
創(chuàng)建表結(jié)構(gòu)
CREATE TABLE `tb_ids` (
`ID` int(11) DEFAULT NULL COMMENT '編碼',
`object` varchar(100) DEFAULT NULL COMMENT '對(duì)象',
`segment` varchar(100) DEFAULT NULL COMMENT '切分段落',
`prefix` varchar(10) DEFAULT NULL COMMENT '前綴',
`format` varchar(50) DEFAULT NULL COMMENT '段落格式',
`length` int(11) DEFAULT NULL COMMENT '數(shù)字長(zhǎng)度',
`sequence` int(11) DEFAULT NULL COMMENT '當(dāng)前序列',
`suffix` varchar(10) DEFAULT NULL COMMENT '后綴',
`type` int(11) DEFAULT NULL COMMENT '類型[1:持續(xù)累計(jì);2:階段性累計(jì)]'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
初始化數(shù)據(jù)
- 指定前綴拂酣,按日重新累計(jì);
- 指定前綴仲义,從1開始一直累加踱葛;
- 指定前綴丹莲,按年月重新累計(jì);
- 指定前綴尸诽,按兩位年份重新累計(jì)甥材;
INSERT INTO `tb_ids` VALUES ('1', 'ORDER', '20180629', 'R', '%Y%m%d', '6', '0', '', '2');
INSERT INTO `tb_ids` VALUES ('2', 'USER', null, 'U', '', '6', '0', '', '1');
INSERT INTO `tb_ids` VALUES ('3', 'SALE', '201806', 'SO', '%Y%m', '6', '0', '', '2');
INSERT INTO `tb_ids` VALUES ('5', 'YEAR', '18', 'Y', '%y', '6', '0', '', '2');
創(chuàng)建函數(shù)
CREATE FUNCTION `sequnce`(in_object VARCHAR(50)) RETURNS varchar(200) CHARSET utf8
BEGIN
#定義下個(gè)編碼變量
DECLARE next VARCHAR (100);
#定義是否同段內(nèi)的編碼,如果不是從1開始性含。
DECLARE is_same_segment TINYINT (1);
#如果是連續(xù)遞增的編碼,設(shè)置為是同一段的編碼
SELECT
(t.type = 1 ) INTO is_same_segment
FROM
tb_ids t
WHERE
t.object = in_object ;
#如果不是連續(xù)遞增的編碼洲赵,查詢現(xiàn)在時(shí)間和上次編碼生成時(shí)間是否同一個(gè)段落
if (!is_same_segment) then
SELECT
t.segment = DATE_FORMAT(NOW(), t.format) INTO is_same_segment
FROM
tb_ids t
WHERE
t.object = in_object ;
end if;
#更新編碼,如果統(tǒng)一段落加一商蕴,否則從一開始叠萍;更新此次編碼生成的段落;
UPDATE tb_ids t
SET t.sequence = (
CASE
WHEN !is_same_segment THEN # 不同段落從1開始
1
ELSE # 相同段落累計(jì)
sequence + 1
END
),
t.segment = DATE_FORMAT(NOW(), t.format)
WHERE
object = in_object ;
# 根據(jù)前綴绪商、段落苛谷、序號(hào),后綴生成編碼
SELECT
CONCAT(
IFNULL(t.prefix,''),#前綴
IFNULL(DATE_FORMAT(NOW(), t.format),''),#段落
LPAD(sequence, t.length, 0),#序列
IFNULL(t.suffix,'')#后綴
) INTO next
FROM
tb_ids t
WHERE
t.object = in_object ;
RETURN next;
END