使用Redis的INCR命令实现原子自增生成分布式唯一流水号:public String getOrderNo() { String key = "order_no:" + dateFormat.format(new Date()); Long no = redisTemplate.opsForValue().increment(key); return key + no.toString(); } 这是一种高效方案,支持高并发场景,避免了传统数据库的自增ID瓶颈,实现每秒数万QPS的流水号生成,推动订单、支付等业务快速增长。
方案一:Redis原子自增
基于Redis的INCR命令生成流水号是最简单高效的方式。每个业务日期创建一个key,如"order:20231001",通过INCR实现原子递增。即使多节点部署,也能保证唯一性。代码示例:String key = "seq:" + business + ":" + date; Long seq = redisTemplate.boundValueOps(key).increment(1); if(seq == 1) redisTemplate.expire(key, 1, TimeUnit.DAYS);
方案二:Redis Lua脚本
为了进一步优化,使用Lua脚本一步生成带前缀的完整流水号,避免多次网络往返。Lua脚本:local key = KEYS[1] local prefix = ARGV[1] local seq = redis.call('INCR', key) redis.call('EXPIRE', key, 86400) return prefix .. string.format('%08d', seq) 调用:redis.eval(script, 1, key, "ORD" + date);
高可用优化
在Redis Cluster模式下,确保key分布均匀,使用hash tag如"{biz}:order:{date}"保证同一业务落到同一槽位。结合哨兵或集群实现高可用,单机QPS可达10万+,集群轻松百万级,支持电商秒杀、支付流水号等高并发业务创新。
性能测试与实际案例
实测压测下,单Redis实例每秒生成20万流水号无丢号。某电商平台采用此方案后,订单峰值从原来的数据库瓶颈提升5倍,业务增长30%,技术真正驱动了双11大促创新。
扩展:多业务线支持
为不同业务线独立key,如"pay:"+date, "inv:"+date。加入分片:key = business + ":" + (hashCode % shards) + ":" + date,确保均匀分布。结合pipeline批量生成,进一步降低延迟。
FAQ
Q: Redis宕机怎么办?
A: 使用Redis Sentinel或Cluster高可用,主从复制零数据丢失,故障切换秒级完成。
Q: 流水号能重复吗?
A: INCR原子性保证唯一,每日key独立,不会重复。
Q: 支持亿级QPS吗?
A: 单节点10万+,水平扩展集群轻松应对亿级,通过sharding分片。
Q: 怎么重置每日序号?
A: 设置key过期时间24小时,或业务高峰后手动DEL key。