GitHub:https://github.com/qichengzx/seqsvr 欢迎 star。
本项目使用下列优秀的项目作为必要组件。
注意:需要在启动之前创建数据库并修改配置文件中数据库的配置。
go get 方式:
需保证 $GOPATH/bin 在系统 PATH 中。
go get github.com/qichengzx/seqsvr
seqsvr
单独编译:
git clone [email protected]:qichengzx/seqsvr.git
cd seqsvr
go build .
./seqsvr
Docker 方式:
Dockerfile 使用了 Docker 多阶段构建功能,需保证 Docker 版本在 17.05 及以上。详见:Use multi-stage builds
git clone [email protected]:qichengzx/seqsvr.git
cd seqsvr
docker build seqsvr:latest .
docker run -p 8000:8000 seqsvr:latest
数据库名称可以自定义,修改 config.yml 即可。
然后导入以下 SQL 生成数据表。
CREATE TABLE `generator_table` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uuid` char(36) NOT NULL COMMENT '机器识别码',
PRIMARY KEY (`id`),
UNIQUE KEY `id_UNIQUE` (`id`),
UNIQUE KEY `stub_UNIQUE` (`uuid`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
配置文件使用 YAML 格式。
#app
port: ':8000'
#service
step: 100
#db
mysql:
user: 'root'
password: ''
host: 'tcp(localhost:3306)'
database: 'sequence'
可修改端口号及 MySQL 的配置。
curl http://localhost:8000/new
{"code":0,"msg":"ok","data":{"id":101}}
本项目设计原理来自 携程技术中心 的干货 | 分布式架构系统生成全局唯一序列号的一个思路。
服务初始化后第一次请求会在 MySQL 数据库中插入一条数据,以生成初始 ID。
后续的请求,都会在内存中进行自增返回,并且保证返回的 ID 不会超过设置的上限,到达上限后会再次从 MySQL 中更新数据,返回新的初始 ID。
REPLACE INTO `generator_table` (uuid) VALUES ("54f5a3e2-e04c-4664-81db-d7f6a1259d01");
欢迎 star。
1
puritania 2018-07-02 10:59:52 +08:00 via iPhone 1
这个同样要单独部署吧,引入单点 mysql 和线程锁增加了复杂性,悲观情况下可能会有很多问题,我觉得这方案跟 snowflake 比还是不行
|
2
wych 2018-07-02 11:39:20 +08:00
发出来的 ID 是单调递增的么?
|
3
qichengzx OP @puritania
感谢回复。 1.可以单独部署成一个服务,也可以整理成一个包放到已有项目中。项目目前只是以独立服务作为实现。 2.MySQL 的问题,如果请求量不是特别大应该还好。业务量大也可以通过修改步长或 MySQL 增加机器解决。 3.根据携程的介绍是 Java 版使用情况还不错,而且个人认为 Go 的协程开销应该比 Java 低很多。 这个方案与 snowflake 相比,个人觉得原理和实现都比较简单,适合比较初期的项目。 有说的不对的还请指正。 |
5
glacer 2018-07-02 14:17:37 +08:00 1
@qichengzx 通常只有分布式系统(如分布式数据库)才需要用到全局唯一 id,如果是初期的项目,往往根本不需要用分布式系统,根本不存在你这个系统的使用场景啊。
|
6
pathbox 2018-07-02 14:53:02 +08:00 via iPhone
用 redis 的 inc 可以更快
|
8
qichengzx OP @glacer
感谢回复。 没有接触过分布式的系统,至少没有参与过。 写这个的初衷是看到携程的那篇文章,觉得这种方案还挺有意思的,就找时间做了实现,至于实际的使用场景,目前我确实不清楚。 根据文章的介绍,携程是用在了账号系统中。 个人觉得比如 MongoDB,没有数字 ID 的系统中,如果要用到数字 ID,这种方案也是适合的。 |
9
qichengzx OP @pathbox
感谢回复。 关于 Redis 的 incr,原文中也有提到。优缺点引用如下: 优点: 不依赖于数据库,灵活方便,且性能优于数据库。 数字 ID 天然排序,对分页或者需要排序的结果很有帮助。 使用 Redis 集群也可以防止单点故障的问题。 缺点: 如果系统中没有 Redis,还需要引入新的组件,增加系统复杂度。 需要编码和配置的工作量比较大,多环境运维很麻烦, 在开始时,程序实例负载到哪个 redis 实例一旦确定好,未来很难做修改。 |
10
zhouquan03 2018-07-02 19:20:19 +08:00
这样做是有很大风险的。内存进行自增的话,高可用怎么保证?服务挂掉重启怎么保证生成的 id 不重复?
还不如搭建个高可用的 redis,进行 incr 操作,redis QPS 还远远高于 mysql。 |
11
NUT 2018-07-02 19:24:56 +08:00
要说单调递增的 ID 生成,还数 TiDB 的 TSO 牛逼, 设计很轻巧,性能又不差,实现还简单。
|
12
yanaraika 2018-07-02 19:24:57 +08:00
@zhouquan03 redis 也没法保证生成 id 不重复吧
|
13
yanaraika 2018-07-02 19:30:53 +08:00
@zhouquan03 除非用基于 Raft 的 floyd,否则 rust-cluster 默认都是最终一致性。但 Raft 引起的性能下降很严重
|
15
qichengzx OP @zhouquan03 服务挂掉重启后,会从数据库重新写一条记录拿到一个新的 ID 做起点。
|
16
rahuahua 2018-07-03 12:04:02 +08:00
如果是单台 mysql,肯定不能算高可用,如果要搭集群 mysql,对于项目初期过于复杂了。
|