基于redis的分布式ID生成器

原创 2015年03月13日 19:22:59

项目地址

https://github.com/hengyunabc/redis-id-generator

基于redis的分布式ID生成器。

准备

首先,要知道redis的EVAL,EVALSHA命令:

http://redis.readthedocs.org/en/latest/script/eval.html

http://redis.readthedocs.org/en/latest/script/evalsha.html

原理

利用redis的lua脚本执行功能,在每个节点上通过lua脚本生成唯一ID。
生成的ID是64位的:

  • 使用41 bit来存放时间,精确到毫秒,可以使用41年。
  • 使用12 bit来存放逻辑分片ID,最大分片ID是4095
  • 使用10 bit来存放自增长ID,意味着每个节点,每毫秒最多可以生成1024个ID

比如GTM时间 Fri Mar 13 10:00:00 CST 2015 ,它的距1970年的毫秒数是 1426212000000,假定分片ID是53,自增长序列是4,则生成的ID是:

5981966696448054276 = 1426212000000 << 22 + 53 << 10 + 4

redis提供了TIME命令,可以取得redis服务器上的秒数和微秒数。因些lua脚本返回的是一个四元组。

second, microSecond, partition, seq

客户端要自己处理,生成最终ID。

((second * 1000 + microSecond / 1000) << (12 + 10)) + (shardId << 10) + seq;

集群实现原理

假定集群里有3个节点,则节点1返回的seq是:

0, 3, 6, 9, 12 ...

节点2返回的seq是

1, 4, 7, 10, 13 ...

节点3返回的seq是

2, 5, 8, 11, 14 ...

这样每个节点返回的数据都是唯一的。

单个节点部署

下载redis-script-node1.lua,并把它load到redis上。

cd redis-directory/
wget https://raw.githubusercontent.com/hengyunabc/redis-id-generator/master/redis-script-node1.lua
./redis-cli script load "$(cat redis-script-node1.lua)" 

获取lua脚本的sha1值,可能是:

fce3758b2e0af6cbf8fea4d42b379cd0dc374418

在代码里,通过EVALSHA命令,传递这个sha1值,就可以得到生成的ID。

比如,通过命令行执行:

./redis-cli EVALSHA fce3758b2e0af6cbf8fea4d42b379cd0dc374418 2 test 123456789

结果可能是:

1) (integer) 1426238286
2) (integer) 130532
3) (integer) 277
4) (integer) 4

集群部署

假定集群是3个节点,则分别对三个节点执行:

./redis-cli -host node1 -p 6379 script load "$(cat redis-script-node1.lua)" 
./redis-cli -host node2 -p 7379 script load "$(cat redis-script-node2.lua)" 
./redis-cli -host node3 -p 8379 script load "$(cat redis-script-node3.lua)" 

性能

redis默认配置。

单节点,单线程:
time:0:00:00.959
speed:10427.52867570386
单节点,20线程:
time:0:00:06.710
speed:29806.259314456034

结论:
- 单节点,qps约3w
- 可以线性扩展,3个结点足以满足绝大部分的应用

java客户端封装

在redis-id-generator-java目录下,有example和benchmark代码。

在调用时,要传入两个参数
- tag,即为哪一类服务生成ID
- shardId,即分片由哪个ID生成,比如一个用户的订单,则分片ID应该由userId来生成

public class Example {

    public static void main(String[] args) {
        String tab = "order";
        long userId = 123456789;

        IdGenerator idGenerator = IdGenerator.builder()
                .addHost("127.0.0.1", 6379, "fce3758b2e0af6cbf8fea4d42b379cd0dc374418")
//              .addHost("127.0.0.1", 7379, "1abc55928f37176cb934fc7a65069bf32282d817")
//              .addHost("127.0.0.1", 8379, "b056d20feb3f89483b10c81027440cbf6920f74f")
                .build();

        long id = idGenerator.next(tab, userId);

        System.out.println("id:" + id);
        List<Long> result = IdGenerator.parseId(id);

        System.out.println("miliSeconds:" + result.get(0) + ", partition:"
                + result.get(1) + ", seq:" + result.get(2));
    }
}

多语言客户端

只要支持redis evalsha命令就可以了。

其它

之前写的一个blog:分片(Sharding)的全局ID生成

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【redis】使用redis RedisAtomicLong生成自增的ID值

本文介绍在spring+redis组合时,使用redis的RedisAtomicLong生成自增的ID值。 1、自增ID生成类 RedisSequenceFactory是一个简单封装类,用于使用r...
  • yxtouch
  • yxtouch
  • 2017年06月20日 19:40
  • 2228

Redis在集群环境中生成唯一ID

概述设计目标:每秒最大生成10万个ID,ID单调递增且唯一。Reidis可以不需要持久化ID。 要求:集群时钟不能倒退。 总体思路:集群中每个节点预生成生成ID;然后与redis的已经存在的ID做...

redis ID生成器

public class IdSeqGenerator { /** * 昵称计数器,确保唯一性 */ private static final String ID_...

如何用redis来生成唯一Id

在之前的项目中需要用到一个自动增长的主键,该主键需要包含字母,所以没有办法用到数据库的自增主键。楼主要高手的指导下,发现redis的RedisAtomicLong类可以解决这个麻烦。而且redis为单...

基于redis的分布式ID生成器

项目地址 https://github.com/hengyunabc/redis-id-generator 基于redis的分布式ID生成器。 准备 首先,要知道redis的E...

全局唯一ID生成方案

一旦数据库被切分到多个物理结点上,我们将不能再依赖数据库自身的主键生成机制。一方面,某个分区数据库自生成的ID无法保证在全局上是唯一的;另一方面,应用程序在插入数据之前需要先获得ID,以便进行SQL路...

高并发分布式系统中生成全局唯一Id汇总

数据在分片时,典型的是分库分表,就有一个全局ID生成的问题。 单纯的生成全局ID并不是什么难题,但是生成的ID通常要满足分片的一些要求:    1 不能有单点故障。    2 以时间为序,或者I...

如何在高并发分布式系统中生成全局唯一Id

但这篇博文实际上是“半分享半讨论”的博文: 1)         半分享是我将说下我所了解到的关于今天主题所涉及的几种方案。 2)         半讨论是我希望大家对各个方案都说说自己的见解,更加希...
  • houkai6
  • houkai6
  • 2013年12月31日 13:59
  • 21519

高并发分布式环境中获取全局唯一ID[分布式数据库全局唯一主键生成]

需求说明在过去单机系统中,生成唯一ID比较简单,可以使用mysql的自增主键或者oracle中的sequence, 在现在的大型高并发分布式系统中,以上策略就会有问题了,因为不同的数据库会部署到不同的...

分布式系统唯一ID生成方案汇总

系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结。生成ID的方法有很多,适应不同的场景、需求以及性能要求。所以有些比较复杂的系统会有多个ID生成的策略。下面就介绍一些常见...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:基于redis的分布式ID生成器
举报原因:
原因补充:

(最多只允许输入30个字)