全局序号生成器,无需使用关系数据库

时间:2018-11-14 15:02:15

标签: c# database sequential event-store

我有一个申请。假设它是发票服务。每次用户创建发票时,我都需要分配下一个序列号(即:ISequentialNumberGeneratorRepository.Next();,因此尽管我的应用程序正在运行多个实例,但发票号本质上必须是唯一的(将来可能会出现水平可伸缩性)。 / p>

换句话说,我需要一个全局序号生成器。

通常,通过使用关系数据库(例如SQL Server,PostgreSQL,MySQL等)可以解决此问题,因为这些系统具有在插入记录并作为同一原子的一部分返回生成的ID时生成顺序唯一ID的能力。操作,因此它们非常适合集中式序号生成器。

但是我没有关系数据库,并且我不需要一个关系数据库,因此仅使用一个数据库来实现这一微小功能就有点残酷。

但是,我有一个可用的EventStore(EventStore.org),但我无法确定它是否具有序号生成功能。

所以我的问题是:是否有可用的产品可以用来生成唯一的序列号,以便可以实现Next();存储库的方法,并且可以独立于多少个实例正常工作?我有我的客户发票申请吗?

注意:或者,如果有人能想到一种使用EventStore的方法,或者在DDD / CQRS / ES环境中如何实现此目的,那也很棒。

3 个答案:

答案 0 :(得分:1)

恕我直言,您的要求有些瑕疵,因为您的需求存在冲突。

您想要一个唯一的ID。常用的解决方案是:

  • 向导。可以集中生成或本地生成。真的很容易实现。 Kinda对于人类读者来说很难,但是YMMV。但是您需要增量密钥。
  • 中央分配的密钥:您需要一个交易系统。但是您想执行CQRS,并使用事件存储。在我看来,仅拥有IDENTITY_COLUMNSEQUENCE的独立交易系统在很大程度上忽略了进行CQRS的目的。
  • 使用HiLo生成方法。那就是:每个客户都有一个独特的种子(例如第一个客户10亿,第二个客户20亿,等等)。因此,每个客户端都可以在本地生成一个序列。此序列是分布式的,并且使用序号,因此没有并发问题,但是没有针对请求的全局排序,您必须确保没有两个客户端获得相同的Hi值(相对简单的任务)。
  • 使用事件存储分配的ID。我不知道产品,但是发送到队列的每个事件都有一个唯一的ID。但是(据我了解),在发送事件之前,您需要提供ID。

通常可以将这两种解决方案(尤其是Hilo算法)与时间戳(例如Unix Epoch中的秒数之类的东西)混合搭配,以产生(较弱且无法保证的)排序能力。但是通常我会避免这种情况,因为如果您在多个站点上生成ID,则会带来时钟不同步的风险,通常还会带来其他未解决(或无法解决)的问题。

可能我错过了一些东西,但这是我脑海中的那些东西。

据我所知,你是一个模范。我会非常努力地使自己处于上述情况之一。

答案 1 :(得分:1)

您尚未说明为什么需要此功能的原因(或提供任何代码)。我将假设“顺序”一词应视为单调递增(排序而不是循环)。

我倾向于同意基耶萨(A.Chiesa),我会在列表中添加时间戳,尽管此处不适用。

由于您的帖子没有说明如何使用数据,因此我有两种解决方案,如果可能的话,第二种方案要优先于第一种方案;对于以后的所有访问者,请改用数据库解决方案。

在没有聚合的情况下跨水平扩展的应用程序保证数字顺序的唯一方法是利用中央服务器分配数字(使用REST或RPC或自定义网络代码;更不用说SQL)服务器,作为旁注)。由于并发性,应用程序必须等待轮到下一个数字,包括网络使用情况和延迟,此延迟限制了应用程序的可伸缩性,并提供了单点故障。通过创建中央服务器的多个实例和多个应用程序池,可以将这些风险降到最低(您将失去全局排序功能)。

作为替代方案,我建议结合批量聚合的HI / LO分配方法。每个实例有四个?每个实例前面加一个递增数字的数字标识符。在中央服务器(或多个冗余服务器)上调度聚合任务以拾取数据并在聚合期间分配顺序唯一ID。此过程对数据进行本地化(直到拾取为止,如果需要相干,则可以安排为(100、500、1000)?毫秒间隔;如果没有,则为几分钟或更长),并提供几乎完美的水平缩放比例,缺点是垂直方向增加聚合服务器上的扩展要求。

分布式处理是处理,内存和通信开销之间的一种平衡行为。无法根据您的帖子确定您的计算/内存/网络容量边界位于何处。

没有一个正确的答案。我为您提供了两种可能性,但是如果手头任务没有特定要求,我将无能为力。

答案 2 :(得分:0)

这是奇怪的看法

  

所以只为这个小东西使用一个有点残酷   功能。

如今,即使在手机中,SQLite仍被用作关系数据库。它很简单,具有较小的内存占用空间,并具有对所有流行编程语言的绑定。 20年前,数据库消耗了许多资源-今天,您可以找到所有任务的数据库引擎。另外,如果您需要很小的密钥对存储,则可以使用BerkeleyDB。