一个兼容 Redis 协议的 ID 生成器

2016-04-07 13:55:28 +08:00
 flikecn

idgo 简介

1. idgo 特点

idgo 是一个利用 MySQL 批量生成 ID 的 ID 生成器, 主要有以下特点:

业界已经有利于 MySQL 生成 ID 的方案,都是通过:

REPLACE INTO Tickets64 (stub) VALUES ('a');
SELECT LAST_INSERT_ID();

这种方式生成 ID 的弊端就是每生成一个 ID 都需要查询一下 MySQL,当 ID 生成过快时会对 MySQL 造成很大的压力。这正式我开发这个项目的原因。服务端兼容 Redis 协议是为了避免单独开发和 idgo 通信的 SDK 。

2. idgo 架构

idgo 和前端应用是才有 redis 协议通信的,然后每个id_key是存储在 MySQL 数据库中,每个 key 会在 MySQL 中生成一张表,表中只有一条记录。这样做的目的是保证当 idgo 由于意外崩溃后,id_key对应的值不会丢失,这样就避免产生了 id 回绕的风险。

idgo 目前只支持四个 redis 命令:

1 . SET key value,通过这个操作设置 id 生成器的初始值。
例如: SET abc 123
2. GET key,通过该命令获取 id 。
3. EXISTS key,查看一个 key 是否存在。
4. DEL key,删除一个 key 。

3. 安装和使用 idgo

  1. 安装 idgo
	1. 安装 Go 语言环境( Go 版本 1.3 以上),具体步骤请 Google 。
	2. 安装 godep 工具, go get github.com/tools/godep 。 
	2. git clone https://github.com/flike/idgo src/github.com/flike/idgo
	3. cd src/github.com/flike/idgo
	4. source ./dev.sh
	5. make
	6. 设置配置文件
	7. 运行 idgo 。./bin/idgo -config=etc/idgo.toml

设置配置文件(etc/idgo.toml):

#idgo 的 IP 和 port
addr="127.0.0.1:6389"
#log_path: /Users/flike/src 
#日志级别
log_level="debug"

[storage_db]
mysql_host="127.0.0.1"
mysql_port=3306
db_name="idgo_test"
user="root"
password=""
max_idle_conns=64

操作演示:

#启动 idgo
➜  idgo git:(master) ✗ ./bin/idgo -config=etc/idgo.toml
2016/04/07 11:51:20 - INFO - server.go:[62] - [server] "NewServer" "Server running" "netProto=tcp|address=127.0.0.1:6389" req_id=0
2016/04/07 11:51:20 - INFO - main.go:[80] - [main] "main" "Idgo start!" "" req_id=0

#启动一个客户端连接 idgo
➜  ~  redis-cli -p 6389
redis 127.0.0.1:6389> get abc
(integer) 0
redis 127.0.0.1:6389> set abc 100
OK
redis 127.0.0.1:6389> get abc
(integer) 101
redis 127.0.0.1:6389> get abc
(integer) 102
redis 127.0.0.1:6389> get abc
(integer) 103
redis 127.0.0.1:6389> get abc
(integer) 104
redis 127.0.0.1:6389>

4. 压力测试

压测环境

|类别|名称| |---|---| |OS |CentOS release 6.4| |CPU |Common KVM CPU @ 2.13GHz| |RAM |2GB| |DISK |50GB| |Mysql |5.1.73|

本地 mac 连接远程该 MySQL 实例压测 ID 生成服务。 每秒中可以生成 20 多万个 ID 。性能方面完全不会有瓶颈。

5.ID 生成服务宕机后的恢复方案

当 idgo 服务意外宕机后,可以切从库,然后将 idgo 对应的 key 加上适当的偏移量。

License

MIT

开源地址: https://github.com/flike/idgo

2240 次点击
所在节点    Go 编程语言
30 条回复
flikecn
2016-04-07 14:04:30 +08:00
一个兼容 Redis 协议的 ID 生成器
surfire91
2016-04-07 14:49:52 +08:00
这与直接用 redis ,有什么区别?或者说有什么优势?
moro
2016-04-07 14:54:59 +08:00
@surfire91 应该是实现一个精简版的 redis ,只用于生成自增 ID 吧。
skydiver
2016-04-07 14:57:27 +08:00
@moro 一点都没精简, mysql 比 redis 还重
skydiver
2016-04-07 15:02:42 +08:00
如果是生成 id 依赖 mysql ,那么为什么不直接用 mysql
如果生成 id 不依赖 mysql ,只是拿 mysql 当存储,那么为啥要用 mysql
noahzh
2016-04-07 15:06:46 +08:00
建议去除 mysql,至于唯一 id 生成可以采用 mysql uuid_short 函数实现
shiny
2016-04-07 15:08:05 +08:00
还不如装个 redis 来 INCR 呢
flikecn
2016-04-07 15:15:22 +08:00
@surfire91 直接用 redis ,一旦机器宕机, id 生成器对应的 key 计数器有可能没有及时保存到磁盘(在内存中),然后重启机器从 rdb 中恢复的话, id 会回绕。重新生成已经生成过的 id 。
flikecn
2016-04-07 15:17:09 +08:00
@skydiver 用 MySQL 的原因就是将 ID 值存在 MySQL 中,宕机重启后,这个值不会回退。兼容 Redis 协议的目的是不想让客户端实现一个 SDK 和 idgo 通信。可以直接用 redis 的 sdk 直连 idgo 。
flikecn
2016-04-07 15:18:51 +08:00
@noahzh 还有个原因就是想生成的 ID 是数字,然后这样用于 MySQL 分表比较分表。
flikecn
2016-04-07 15:19:33 +08:00
@skydiver 生成 ID 依赖于 MySQL 事务,以事务的方式实现批量生成 ID
noahzh
2016-04-07 15:21:16 +08:00
@flikecn 那个生成就是数字,也是连续的,我也是用来数据库分表的,可以直接集成到你的 proxy 里.
flikecn
2016-04-07 15:22:56 +08:00
@noahzh 开发 idgo 确实是有补齐 kingshard 分表的目的。至于是否集成,我还在考虑。:)
skydiver
2016-04-07 15:32:23 +08:00
@flikecn 用事务怎么生成 id ?能不能具体说一下?

说明里只说了常用的方法是什么,没说自己的方法是什么,这也是我看完之后第一个疑问
skydiver
2016-04-07 15:34:28 +08:00
@flikecn redis 可以不用 snapshot 模式,可以用 append only file ,不用担心宕机数据丢失。
noahzh
2016-04-07 15:46:31 +08:00
@flikecn 我觉得你的 proxy 可以用我们的方案配置直接存储到 etcd 中去.
flikecn
2016-04-07 16:01:07 +08:00
@skydiver 恩,但主要我们线上的机器都是 RDB 方式。而且 AOF 也有可能丢失 1s 的数据。基于这个考虑放弃了用 redis 生成 id 的方案。
flikecn
2016-04-07 16:04:18 +08:00
@skydiver 通过事务的方式 update 唯一的一条记录,比如将 1000 修改为 2000 。那么然后 idgo 就可以在本地分配 1000-2000 之间的 id 了。
flikecn
2016-04-07 16:04:56 +08:00
@noahzh 你们的方案在哪?我参考一下。:)
skydiver
2016-04-07 16:09:19 +08:00
@flikecn 所以是每 1000 条修改一次数据库?中间如果挂掉怎么办

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/269235

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX