分布式环境下取流水号

本文介绍了在分布式系统环境下,如何利用Redis的分布式锁来实现流水号的生成。通过VS2022+.Net6+Docker+Redis+Mysql的开发环境,创建MySQL表记录流水号,启动Redis容器,编写核心代码实现加锁获取流水号并更新数据库,最后通过测试验证了流水号的唯一性。这种方法为分布式系统中的流水号生成提供了一种解决方案。

Redis分布式锁取流水号

前言

在日常开发工作中,许多业务场景涉及到取流水号,今天给大家分享一种分布式系统架构环境中取流水号的方案,利用Redis的分布式锁获取流水号。


开发环境

VS2022+.Net6+Docker+Redis+Mysql

开发步骤

1.MySQL数据库新建一个datatable:tb_seqno,新建num字段记录当前流水号

这里简单定义了一个int类型字段,默认值为1
如下(示例):

在这里插入图片描述

2.启动Redis容器

如下(示例):

在这里插入图片描述

3.核心代码编写

新建一个控制台程序,新建一个类文件SeqNo,写入以下代码(需Nuget引入CSRedisCore):

        public static string GetSeqNoByRedisLock()
        {
            using var csredis = new CSRedis.CSRedisClient("192.168.11.112:6379, defaultDatabase = 0, poolsize = 500, ssl = false, writeBuffer = 10240");
            RedisHelper.Initialization(csredis);
            string getSeqNosql = "select num from tb_seqno";
            string updateSeqNoSql = "update tb_seqno set num=num+1";

            var seqNo = string.Empty;
            using (csredis.Lock("test", 5000))
            {
                seqNo = MysqlHelper.ExecuteScalar(getSeqNosql).ToString();

                MysqlHelper.ExecuteNonQuery(updateSeqNoSql);
            }
            return seqNo!;

        }

4.测试

在Program中调用GetSeqNoByRedisLock方法,并打印取出的流水号,使用命令行启动多个项目用来模拟分布式架构环境下的多台机器请求

如下(示例):在这里插入图片描述
结果如下(示例):
在这里插入图片描述


总结

通过控制打印的结果来看并没有出现重复的流水号,这里通过一个简单的Demo给大家分享一种可行性方案,当然实际业务中还需要根据自己的业务需求自定义流水号规则,业务逻辑处理等等,笔者希望此文能起到抛砖引玉的作用,如能给各位朋友一点启发或者帮助那是再好不过。

### Java项目中业务流水号的设计方案和最佳实践 #### 设计原则 为了确保业务流水号的独特性和可追溯性,在Java项目中的设计方案应遵循以下几点: - **唯一性**:保证在同一时间范围内生成的每一个编号都是唯一的。 - **有序性**:如果应用场景有需求,则可以考虑让流水号具备一定的顺序特性,这有助于后续查询统计工作。 - **高效性**:算法执行效率高,不影响系统的整体性能。 #### 方案实现方式 ##### 使用UUID作为基础构建自定义编码逻辑 通过`java.util.UUID.randomUUID()`方法获全局唯一标识符(UUID),再基于此创建满足特定格式要求的字符串形式的业务流水号。这种方式简单易行,能有效防止冲突发生[^1]。 ```java import java.util.UUID; public class BusinessSerialNumberGenerator { public static String generate() { UUID uuid = UUID.randomUUID(); return "BS-" + uuid.toString().replaceAll("-", "").toUpperCase(); // 自定义前缀加上去除了连字符并转换成大写的UUID值 } } ``` ##### 利用数据库序列(Sequence) 对于支持序列功能的关系型数据库而言,可以直接利用其内置机制来分配连续整数值,并将其转化为指定长度与格式后的字符串表示法用于构成最终版本的业务流水号。这种方法适用于那些对数据一致性有着严格要求的应用场景下[^3]。 ```sql CREATE SEQUENCE business_serial_seq START WITH 1 INCREMENT BY 1; ``` ```java // 假设有一个名为get_nextval_from_db的方法可以从DB到下一个sequence value String formatPattern = "%08d"; // 定义填充模式为八位数宽度不足补零 int nextVal = get_nextval_from_db("business_serial_seq"); return String.format(formatPattern, nextVal); ``` ##### 集中式服务提供者模型 当面临分布式环境下的多实例部署情况时,可以通过建立专门负责生产此类号码的服务节点集群来解决跨机器间同步问题。客户端应用程序每次请求新的ID都会向该类服务器发起调用获得结果返回给调用方使用。这种架构虽然增加了系统复杂度但是却很好地解决了大规模并发访问条件下的资源竞争难题[^2]。 ```java // 这里仅示意远程接口调用过程,实际开发需结合具体RPC框架完成细节部分编写 public interface RemoteIdService { Long getNextBusinessSerialNo(); } RemoteIdService remoteIdService; // 实际应用中应当注入真实的代理对象实例 Long serialNo = remoteIdService.getNextBusinessSerialNo(); System.out.println(serialNo); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值