通用的序列号生成器库
正如文章《通用的业务编号规则设计实现(附源码)》 文章里需要一个多实例和线程安全的序列化生成器,在SQL Server 2012+ 版本 有一个通过.NET程序集的序列号transact-sql 函数 http://msdn.microsoft.com/zh-cn/library/ff878091.aspx。 这篇文章向大家介绍一个使用SQL Server 和Sql Azure 以及Mongodb 实现的序列号生成器。
在Github上有个项目 https://github.com/getAddress/Sequence ,我Fork了一份,增加了一个Mongodb 实现,地址是https://github.com/geffzhang/Sequence。下面我介绍下使用Mongodb实现的sequence 存储,主要就是实现接口IstateStore。
这里实现的关键点就是在更新数据的时候如何保证原子性的操作,Mongo 可以使用findAndModify命令, findAndModify可以从数据库查找返回一个文档的同时更新/插入/删除文档,原子操作,线程安全,功能强大,原型复杂。
public async Task<bool> UpdateAsync(SequenceKey sequenceKey, ISequence sequence)
{
var sequenceEntity = sequence as Sequences;
sequenceEntity.Id = sequenceKey.Value;
var query = Query.And(Query.EQ("_id", ObjectId.Parse(sequenceKey.Value)));
var update = MongoDB.Driver.Builders.Update < Sequences>.Set( c => c.CurrentValue , sequenceEntity.CurrentValue);
var updatedSequenceEntity = this.Collection.FindAndModify(new FindAndModifyArgs() { Query = query, Update = update, VersionReturned = FindAndModifyDocumentVersion.Original, SortBy = null });
var doc = updatedSequenceEntity.ModifiedDocument;
return doc != null;
}
findAndModify命令中每个键对应的值如下所示。
findAndModify 字符窜,集合名。
query 查询文档,用来检索文档的条件。
sort 排序结果的条件。
update 修改器文档,对所找到的文档执行的更新。
remove 布尔类型,表示是否删除文档。
new 布尔类型,表示返回的是更新前的文档还是更新后的文档。默认是更新前的文档。
"update"和"remove"必须有一个,也只能有一个。要是匹配不到文档,这个命令会返回一个错误。
这个命令有些限制。它一次只能处理一个文档,也不能执行upsert操作,只能更新已有文档。
相比普通更新来说,findAndModify速度要慢一些。大概耗时相当于一次查找,一次更新和一次getLastError顺序执行所需的时间。
使用起来非常简单,下面我们使用Mongodb 作为代码示例:
通过Nuget 安装getAddress.Sequence.Mongo:
- 根据业务需求创建一个序列化生成器,也就是SequenceKey ,Mongo 使用它的ObjectId 来作为Key
var stateProvider = GetStateProvider();
var sequenceGenerator = new SequenceGenerator(stateProvider);
var sequence = await CreateSequence(stateProvider,increment: 0, startAt: 5);
var sequenceKey = await stateProvider.AddAsync(sequence);
2. 使用这个SequenceKey 就可以用调用了
var stateProvider = GetStateProvider();
var sequenceGenerator = new SequenceGenerator(stateProvider);
var nextValue1 = await sequenceGenerator.NextAsync(new SequenceKey { Value = "56af206c7c2a5827389ad412"});
项目里有完整的单元测试用例,跑完整个单元测试用例,Mongodb的数据展示一下:
我们把数据存储在一个叫做Sequences的Collection里,_id 列就是我们的sequenceKey。StartAt 表示起点, Increment 表示步长, MaxValue 表示最大值, MinValue 表示最小值,Cycle 表示达到最大值,从头开始循环,CurrentValue 表示当前值。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 实现 Base64 的编码解码
- Android实现底部导航栏的主界面
- Spring注解@Autowired源码分析
- 使用RecyclerView实现水平列表
- android实现记住用户名和密码以及自动登录
- Android碎片fragment实现静态加载的实例代码
- android异步消息机制 源码层面彻底解析(1)
- /undefinedcss/modules/layer/default/layer.css?v=3.1.1找不到的问题
- Android实现渐变启动页和带有指示器的引导页
- the input device is not a TTY. If you are using mintty, try prefixing the comma
- 【STM32F407】第13章 RL-TCPnet V7.X之创建多个TCP客户端
- RecyclerView实现列表倒计时
- wsl设置默认账户为root(ubuntu18.04)
- LeetCode No.14 最长公共前缀
- android异步消息机制 从源码层面解析(2)