ID生成器是指能产生不重复ID服务的程序,在后台开发过程中,尤其是分布式服务、微服务程序开发过程中,经常会用到,例如,为用户的每个请求产生一个唯一ID、为每个消息产生一个ID等等,ID生成器也是进行无状态服务开发的重要需求之一。

ID生成器有其特殊要求:

(1)    产生的ID不能重复,在任何情况下产生的ID都不能重复,例如:在ID生成器程序重启之后,ID生成器产生的新ID不能与重启之前产生的ID重复;

(2)    ID尽可能短小,由于很多情况下,ID需要被存储或者传输,因此在满足ID不重复的基础上ID长度尽可能短小,以降低存储或传输资源的浪费;

(3)    支持高并发低延时请求,ID生成器需要应付大量的请求服务,因此要提供高并发的请求,同时要求请求响应的延时时间尽可能小,一般在10毫秒以内;

(4)    支持多ID,在实际开发过程中,有太多的情形都需要ID服务,例如:每个消息、每个用户请求、每次事务的处理等等,这些不同的应用场景都需要自己的ID,因此ID生成器需要满足同时为不各应用场景产生不同ID的服务;

(5)    在特殊场合下还需要满足ID有序,例如递增或者递减;

(6)    高可靠服务,在ID生成器的实际部署过程中,可能会遇到断电、断网、程序异常崩溃等等各种奇怪的问题,因此,如何能保证ID生成器提供稳定高效的服务,是分布式服务开发过程中,首先要解决的问题。

下面将介绍如何使用redis的INCR来快速开发一个满足上述需要的ID生成器服务,INCR命令是Redis针对value为字符串操作,它要求value的最大值为64位,每次操作将redis中的value值加1,并返回递增之后的值。其架构如下所示:


使用redis作为ID生成器的数据源,为满足ID生成器的特殊要求,需特殊部署redis:

(1)    要启用两个独立的redis,这里的两个redis需要独立部署,尽量不要和其他业务复用redis;

(2)    两个redis一个为主一个为从,主提供ID生产服务,从做持久化,从而保证数据源的高效、安全;

上述部署中,按照如下方式满足ID生成器的特殊需求:

(1)    用主redis提供产生ID服务,但不进行持久化操作,Redis本身的高性能可满足ID生成器的高性能和低延时的要求,在实际测试过程中,可产生300多万/秒的ID,且请求延时为1~2毫秒;

(2)    用从Redis做持久化,保证在master挂掉之后,slave能提供服务,主从全部挂掉之后,ID数据源也被持久化到了硬盘,从而保证重新启动redis之后,ID会从持久化的位置开始产生,就不会再产生重复的ID;

(3)    redis本身的key-value机制就可以提供多种ID服务,只需要为每个需求的ID产生不同的key值即可,例如在redis中消息ID的key为“id.msg”,日志ID的key值为“id.log”等等,这样消息的ID和日志的ID就可以独自完成递增操作而互补干扰。

(4)    redis的INCR和DECR两个指令,可以产生递增或者递减的ID服务;

(5)    redis的ID的类型最大长度为64位,可以从0开始,依次递增产生,所产生的ID就是最短的;

如果项目紧急,使用上述方式就可以很快搭建一个ID生成器服务,但是上诉ID生成器服务还存在一些缺陷:

(1)    与应用耦合高,没有对外屏蔽掉内部实现细节,例如redis,在使用时,用户完全不需要知道ID生成器使用什么产生的ID;

(2)    扩展性差,在项目规模较大时,ID的应用会非常多,如果用一个redis无法满足需求时,不方面扩展;

真正的ID生成器服务还需解决上述问题。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐