流水编号

日常在我们开发的过程中可能会用到编号的功能,如销售订单号,采购订单号,日志编号,凭证号...等等,为了保证唯一有些表的主键要么用自增长,要么用GUID值,或通过雪花ID算法生成。这此方式基本都能产生唯一的ID,但如果在分布式环境下产生流水ID,以上这几种方式可能就不太好用,如有以下场景

  1. 工作流的流水编号

工作流的编号通常会是以下格式 如2022060200001-2022060299999 到了第二天时尾数又要生00001开始编,这种编号规则有一个好处就是非常直观的通过工作流编号就可以看出来这是哪一天申请的流程,一天大概有多少流水码。那么如果我们用常规编号规则其实是比较难完成此需求的。

  1. 采购订单号

如在实际业务需求中 标准采购订单要用5000000000-5999999999 这个号进行进行编码,委外采购订单用4000000000-4999999999号段进行编码

  1. XX业务受理单编号

在办里某业务时根据业务类型使用不同的编号 如财务收款用的流水号是 SK10000000-SK99999999,支出用的是ZC10000000-ZC99999999

根据以上的业务场景如果使用常规的编号是比较难实现的(要保证分布式环境编号不重复且按流水编码),那么HiSql 提供了比较方便的解决方案

该版本还未正式更新nuget 需要使用请下载源码

怎样开启编号规则

  //如果需要使用编号那么一定要开启此功能
HiSql.Global.SnroOn = true; //开启编号后进行初始化
sqlClient.CodeFirst.InstallHisql();//仅需执行一次 如果使用的低版本的HiSql 升级引用包手需要重新初始化安装

初始安装完成后会生成表Hi_Snro 这个编号配置表

编号配置介绍

Hi_Snro 表详细说明

字段 描述 备注
SNRO 编号规则名称 主键 字符串(10)
SNUM 子编号 主键 整数
IsSnow 是否雪花ID bool true:表示雪花id false:表示自定义流水编号
SnowTick 雪花ID时间戳 int64 IsSnow 为true时配置 大于0 都可以,其它的都可以不用配置
StartNum 编号开始值 字符串(20) 当IsNumber 为true 时编号只能纯数字 为false时 可以以0-9 A-Z 混编
EndNum 编号结束值 字符串(20) 当编号超过此时时将会抛出异常号段池已满
CurrNum 当前编号值 字符串(20) 第一次配置时值要等于StartNum
CurrAllNum 当前完整编号 字符串(40) 不需要配置,产生流水时会自动生成
Length 编号长度 StartNumEndNum 的长度 两者的长度要一至否则会报错
IsNumber 是否纯数字编号 当为true 编号按0-9的10进制数字编号,当为false时按0-9 A-Z 36进度数字和字母混合编号
IsHasPre 是否有前辍 可以按到年月日时分秒作为前辍 在PreType 配置
PreType 前辍编号类型 详细请见 PreType 前置编号类型配置
FixPreChar 固定前辍 固定一个字符串 每个生成的码前面都加上这个值
PreChar 当前前辍 不需要配置 在编号的过程中会将 FixPreCharPreType 存在此昝
CacheSpace 号段缓存 编号使用越频繁这个值配置越大 常的建议配置为10 值越大编号性能越好
CurrCacheSpace 当前缓存池使用的数量 不需要配置
Descript 编号描述 备注一下当前编号规则

PreType 前置编号类型配置

PreType 是一个枚举类

字段 备注
PreType.None 0 表示无前置
PreType.Y 1 表示前置为日期格式[yyyy] 即当前年份如2022
PreType.Y2 12 表示前置为日期格式[yy] 即当前年份后两位如22
PreType.YM 2 表示前置为日期格式[yyyyMM] 即当前年月如202206
PreType.Y2M 22 表示前置为日期格式[yyMM] 即当前年月如2206
PreType.YMD 3 表示前置为日期格式[yyyyMMdd] 即当前年月日如20220602
PreType.Y2MD 32 表示前置为日期格式[yyMMdd] 即当前年月日如220602
PreType.YMDH 4 表示前置为日期格式[yyyyMMddHH] 即当前年月日时如2022060216
PreType.Y2MDH 42 表示前置为日期格式[yyMMddHH] 即当前年月日时如22060216
PreType.YMDHm 5 表示前置为日期格式[yyyyMMddHHmm] 即当前年月日时分如202206021630
PreType.Y2MDHm 52 表示前置为日期格式[yyMMddHHmm] 即当前年月日时分如2206021630
PreType.YMDHms 6 表示前置为日期格式[yyyyMMddHHmmss] 即当前年月日时分秒如20220602163020
PreType.Y2MDHms 62 表示前置为日期格式[yyMMddHHmmss] 即当前年月日时分秒如220602163020

根据以上配置规则将数据配置到表中

配置样例

Hi_Snro 的配置可以自行做个配置界面进行配置,以下是通过程序进行配置保存.

  List<Hi_Snro> list = new List<Hi_Snro>();

  ///工作流编号配置
///按天产生流水号 如2205061000000-2205069999999 之间 list.Add( new Hi_Snro { SNRO = "WFNO", SNUM = 1, IsSnow = false, SnowTick = 0, StartNum = "1000000", EndNum = "9999999", Length = 7, CurrNum = "1000000", IsNumber = true, PreType=PreType.Y2MD, FixPreChar="", IsHasPre = true, CacheSpace = 5, Descript = "工作流编号" }); ///生成销售订单编码 每分钟从0开始编号 如20220602145800001-20220602145899999
list.Add(new Hi_Snro{ SNRO = "SALENO", SNUM = 1, IsSnow = false, SnowTick = 0, StartNum = "10000", EndNum = "99999", Length = 5, CurrNum = "10000", IsNumber = true, PreType = PreType.YMDHm, FixPreChar = "", IsHasPre = true, CacheSpace = 10, Descript = "销售订单号流水" });
///生成另外一种销售订单编码 年的是取后两位 按每秒顺序生成 如22060214581200001-22060214581299999
list.Add(new Hi_Snro { SNRO = "SALENO", SNUM = 2, IsSnow = false, SnowTick = 0, StartNum = "10000", EndNum = "99999", Length = 5, CurrNum = "10000", IsNumber = true, PreType = PreType.Y2MDHms, FixPreChar = "", IsHasPre = true, CacheSpace = 10, Descript = "销售订单号流水" }); ///通过雪花ID生成
list.Add( new Hi_Snro { SNRO = "Order", SNUM = 1, IsSnow=true, SnowTick=145444, StartNum = "", EndNum = "",Length=7, CurrNum = "", IsNumber = true, IsHasPre = false, CacheSpace = 10, Descript = "订单号雪花ID" }); //保存配置到表中
sqlClient.Modi("Hi_Snro", list).ExecCommand();

编号生成代码环境配置

建议把SeriNumber 做成一个局静态变量

  public static SeriNumber number = null;  //定义个全局变更的流水号对象

设置连接

  //sqlClient 为数据库连接对象
number = new SeriNumber(sqlClient);

如果应用进行了分布式布署 请一定要启用以下代码

  HiSql.Global.RedisOn = true;//开启redis缓存
HiSql.Global.RedisOptions = new RedisOptions { Host = "172.16.80.178", PassWord = "qwe123", Port = 6379, CacheRegion = "HRM", Database = 2 }; HiSql.Global.NumberOptions.MultiMode= true; //如果部署了分布式且也要生成雪花ID 一定要配置以下当前应用的ID 多个应用间只要不重复即可0-31之间
HiSql.Global.NumberOptions.WorkId=1;

通过以上配置则分布式编号环境配置完成,下面就可以进行编号测试了

编号测试

为了测试编号是否有重复我这里建了一个测试记录表H_nlog ,编号生成完成后可以分析该表的数据看是否有重复数据,(测试环境 为SqlServer) sql代码如下


SET ANSI_NULLS ON
GO SET QUOTED_IDENTIFIER ON
GO CREATE TABLE [dbo].[H_nlog](
[Nid] [int] IDENTITY(1,1) NOT NULL,
[Numbers] [varchar](50) NULL,
[CreateTime] [datetime] NULL,
[CreateName] [nvarchar](50) NULL,
[ModiTime] [datetime] NULL,
[ModiName] [nvarchar](50) NULL,
CONSTRAINT [PK_H_nlog] PRIMARY KEY CLUSTERED
(
[Nid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO ALTER TABLE [dbo].[H_nlog] ADD CONSTRAINT [DF_H_nlog_CreateTime] DEFAULT (getdate()) FOR [CreateTime]
GO ALTER TABLE [dbo].[H_nlog] ADD CONSTRAINT [DF_H_nlog_CreateName] DEFAULT ('') FOR [CreateName]
GO ALTER TABLE [dbo].[H_nlog] ADD CONSTRAINT [DF_H_nlog_ModiTime] DEFAULT (getdate()) FOR [ModiTime]
GO ALTER TABLE [dbo].[H_nlog] ADD CONSTRAINT [DF_H_nlog_ModiName] DEFAULT ('') FOR [ModiName]
GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建时间' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'H_nlog', @level2type=N'COLUMN',@level2name=N'CreateTime'
GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'创建人' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'H_nlog', @level2type=N'COLUMN',@level2name=N'CreateName'
GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'修改时间' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'H_nlog', @level2type=N'COLUMN',@level2name=N'ModiTime'
GO EXEC sys.sp_addextendedproperty @name=N'MS_Description', @value=N'修改人' , @level0type=N'SCHEMA',@level0name=N'dbo', @level1type=N'TABLE',@level1name=N'H_nlog', @level2type=N'COLUMN',@level2name=N'ModiName'
GO

根据编号规则WFNO 子编号1 生成编号

  List<object> lst = new List<object>();
for (int i = 0; i < 1000; i++)
{
var num = number.NewNumber("WFNO", 1);
lst.Add(new { Numbers = num });
Console.WriteLine(num);
} sqlClient.Insert("H_nlog", lst).ExecCommand();

测试结果

启用了分布式多个应用同时对同一个编号规则产生编号不会产生重复编号。

怎样生成分布式的流水ID的更多相关文章

  1. 框架篇:分布式全局唯一ID

    前言 每一次HTTP请求,数据库的事务的执行,我们追踪代码执行的过程中,需要一个唯一值和这些业务操作相关联,对于单机的系统,可以用数据库的自增ID或者时间戳加一个在本机递增值,即可实现唯一值.但在分布 ...

  2. Zookeeper命名服务——生成分布式有序且唯一id

    生成分布式有序且唯一id的方法有很多种,使用zookeeper是比较简单的一种方法,只是生成的速度不高,这里只是一个借助zk的版本号生成分布式唯一且有序id的例子. ZkIdGenerator.jav ...

  3. 数据库分库分表(一)常见分布式主键ID生成策略

    主键生成策略 系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,下面介绍一些常见的ID生成策略. Sequence ID UUID GUID COMB Snowflake 最开始的自增ID为了实 ...

  4. 全局流水ID号生成的几种方法

    这个问题源自于,我想找一个分布式下的ID生成器.  这个最简单的方案是,数据库自增ID.为啥不用咧?有这么几点原因,一是,会依赖于数据库的具体实现,比如,mysql有自增,oracle没有,得用序列, ...

  5. redis生成分布式id方案

    分布式Id - redis方式   本篇分享内容是关于生成分布式Id的其中之一方案,除了redis方案之外还有如:数据库,雪花算法,mogodb(object_id也是数据库)等方案,对于redis来 ...

  6. (4.24)【mysql、sql server】分布式全局唯一ID生成方案

    参考:分布式全局唯一ID生成方案:https://blog.csdn.net/linzhiqiang0316/article/details/80425437 分表生成唯一ID方案 sql serve ...

  7. 分布式全局唯一ID生成策略

    为什么分布式系统需要用到ID生成系统 在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识.如在美团点评的金融.支付.餐饮.酒店.猫眼电影等产品的系统中,数据日渐增长,对数据库的分库分表后需要有 ...

  8. 常见分布式全局唯一ID生成策略

    全局唯一的 ID 几乎是所有系统都会遇到的刚需.这个 id 在搜索, 存储数据, 加快检索速度 等等很多方面都有着重要的意义.工业上有多种策略来获取这个全局唯一的id,针对常见的几种场景,我在这里进行 ...

  9. 分库分表的 9种分布式主键ID 生成方案,挺全乎的

    <sharding-jdbc 分库分表的 4种分片策略> 中我们介绍了 sharding-jdbc 4种分片策略的使用场景,可以满足基础的分片功能开发,这篇我们来看看分库分表后,应该如何为 ...

随机推荐

  1. 微信小程序页面跳转参数传递

    可以使用标签直接传递 <navigator class="gotoDetail" target="self" url="../detail/de ...

  2. FastAPI(六十六)实战开发《在线课程学习系统》接口开发--用户注册接口开发

    在前面我们分析了接口的设计,那么我们现在做接口的开发. 我们先去设计下pydantic用户参数的校验 from pydantic import BaseModel from typing import ...

  3. Python知识结构

    Python知识结构(点我) 欢迎评论提修改意见

  4. CVE 公开披露的网络安全漏洞列表

    CVE®是一份公开披露的网络安全漏洞列表, 官方地址为 : https://cve.mitre.org/cve/ 比如 mavenrepository 上阿里的Druid修复的漏洞的列表如下:

  5. C# 利用.NET 升级助手将.NET Framework项目升级为.NET 6

    ​概述 .NET6 正式版本已经发布有一阵子了,今天我就体验一下如何将.NET Framework的项目升级为.NET 6. 升级条件: Windows 操作系统 .NET 6 SDK Visual ...

  6. 安卓记账本开发学习day4

    在代码层面,展示出来的界面应该如下图 但是实际运行效果如下图 很明显,"其他"都没有显示出来,经过一点点排查,发现是IncomeFragment.java文件的代码存在错误 @Nu ...

  7. JavaWeb学习day7-Response初学3(重定向)

    重定向:web资源收到客户端请求后,通知客户端去访问另外一个web资源 1 protected void doGet(HttpServletRequest req, HttpServletRespon ...

  8. 2021.11.03 P6175 无向图的最小环问题

    2021.11.03 P6175 无向图的最小环问题 P6175 无向图的最小环问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题意: 给定一张无向图,求图中一个至少包含 33 ...

  9. 初学Java时没有理解的一些概念

    背景 之前学Java属于赶鸭子上架,草草学习基础语法便直接做课程作业,许多概念问题仍不清楚,故在此梳理一下,主要参考廖雪峰和互联网资料. Java运行方式与JVM Java是介于编译型语言(C++)和 ...

  10. 最新MATLAB R2020b超详细安装教程(附完整安装文件)

    摘要:本文详细介绍Matlab R2020b的安装步骤,为方便安装这里提供了完整安装文件的百度网盘下载链接供大家使用.从文件下载到证书安装本文都给出了每个步骤的截图,按照图示进行即可轻松完成安装使用. ...