用Redis搞个统一的用户ID体系,方便又高效不怕重复
- 问答
- 2025-12-26 11:08:15
- 2
这个想法其实挺简单的,就是找一个永远不会重复的“发号器”,专门用来生成用户的ID,这个发号器要非常快,能同时应付成千上万的注册请求,而且保证每个拿到手的号码都是唯一的,我们自己用数据库来生成的话,比如用数据表的主键自增,在用户量不大、服务器只有一台的时候还行,但一旦人多了,或者要把服务部署到多台机器上(也就是分布式环境),这个办法就很容易成为瓶颈,速度慢,还容易出问题。
这时候,Redis就派上用场了,它有几个特别适合干这个活儿的特点,Redis的所有数据都在内存里,所以读写速度飞快,比去硬盘上读写的数据库要快好几个数量级,Redis提供了一些原子操作,这个词听起来有点专业,但意思很简单,一个操作要么完全成功,要么完全失败,不会卡在中间状态”,这对于生成唯一ID至关重要,因为可以确保即使在很多人同时来要号码的情况下,也绝不会发出两个一样的号码。
具体怎么用Redis来实现这个统一的用户ID发号器呢?最常见、最直接的办法就是利用Redis的INCR命令,这个命令的功能就是给一个键(key)对应的数字值增加1,如果这个键不存在,Redis会先把它当成0,然后再加1,关键就在于,INCR是一个原子操作。

我们可以这样做:在Redis里设置一个专门的键,比如就叫它 global:user:id,每当有一个新用户需要注册时,我们的应用程序就向Redis发送一个 INCR global:user:id 命令,Redis会保证每次这个命令都返回一个唯一的、比上一个数字大1的整数,这个整数就是我们给新用户分配的ID,因为操作是原子的,所以完全不用担心在高并发下会出现重复号码的问题,这种方法生成的ID是连续的纯数字,非常简洁。
有时候我们可能不希望ID是简单的、容易被猜到的连续数字,或者我们的系统可能非常庞大,需要把服务部署在多个机房,这时候单纯靠一个Redis实例来发号可能会有单点故障的风险(万一这台Redis服务器挂了,整个系统就无法注册新用户了),为了解决这些问题,我们可以对上面的方法做一些改进,形成一个更健壮的方案。

一个经典的改进方法是“分段发号”,或者叫“号段”模式,这个思路不是每次生成一个ID都去访问一次Redis,而是每次从Redis里申请一批ID号段回来,应用程序A先向Redis请求一个号段,Redis当前的global:user:id值是10000,那么Redis可以一次性把10001到11000这1000个号码分配给应用程序A,同时把global:user:id的值更新为11000,在应用程序A内部,它就可以在内存里慢慢地从10001开始分配这1000个用户ID,而完全不需要再频繁地连接Redis,等这1000个号码快用完了,它再去Redis申请下一个批次的号码,这样做的好处是极大地减少了对Redis的请求次数,性能非常高,而且即使Redis出现短暂的网络抖动,应用程序本地还有备用的ID可以继续服务,增强了系统的可用性。
如果我们有多台Redis服务器(比如做了主从复制或者集群),为了避免不同Redis实例生成的ID冲突,我们还可以结合机器标识来生成ID,我们可以把用户ID设计成由“时间戳”、“机器编号”和“序列号”几部分组合而成,Redis在这里可以负责生成每台机器的序列号部分,或者负责协调一个全局的、不会重复的机器编号,我们可以让每台应用服务器启动时,都去Redis的一个集合里注册一下,Redis给它分配一个唯一的数字作为机器ID,这样,最终生成的用户ID = 时间戳(毫秒级) + 机器ID + 自增序列号,这种方式生成的ID是趋势递增的长数字,既保证了全局唯一,又带有时间信息,还避免了单点依赖。
用Redis构建统一用户ID体系的核心优势就在于:速度极快(内存操作)、能轻松应对高并发(原子操作)、方案灵活可变(可以简单自增,也可以设计复杂结构),无论是简单的INCR命令,还是更高级的号段模式或组合ID模式,Redis都能提供一个可靠、高效的基石,让我们再也不用为生成唯一的用户ID而发愁。
本文由芮以莲于2025-12-26发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/68753.html
