建议的解决方案:在分布式环境中生成唯一 ID

2024-03-12

我一直在浏览网络,试图找到一种解决方案,使我们能够在区域分布式环境中生成唯一的 ID。

我查看了以下选项(除其他外):

雪花(推特)

  • 这似乎是一个很棒的解决方案,但我只是不喜欢仅仅为了创建 ID 而必须管理另一个软件所带来的额外复杂性;
  • 现阶段缺乏文档,所以我认为这不是一个好的投资;
  • 节点需要能够使用 Zookeeper 相互通信(延迟/通信失败怎么办?)

UUID

  • 看看它:550e8400-e29b-41d4-a716-446655440000;
  • 它是一个 128 位 ID;
  • 存在一些已知的冲突(取决于我猜测的版本)看到这个帖子 https://stackoverflow.com/questions/3038023/uuid-collision-risk-using-different-algorithms.

关系数据库(如 MYSQL)中的自动增量

  • 这看起来很安全,但不幸的是,我们没有使用关系数据库(可扩展性偏好);
  • 我们可以为此部署一个 MySQL 服务器,就像 Flickr 所做的那样,但同样,这会引入另一个故障点/瓶颈。也增加了复杂性。

非关系数据库(如 COUCHBASE)中的自动增量

  • 这可以工作,因为我们使用 Couchbase 作为数据库服务器,但是;
  • 当我们在不同地区有多个集群、延迟问题、网络故障时,这一点就行不通了:在某些时候,ID 会根据流量大小而发生冲突;

我建议的解决方案(这是我需要帮助的)

假设我们的集群由 5 个不同区域(非洲、欧洲、亚洲、美洲和大洋洲)的 10 个 Couchbase 节点和 10 个应用程序节点组成。这是为了确保从最靠近用户的位置提供内容(以提高速度)并确保发生灾难等情况时的冗余。

现在,任务是生成在复制(和平衡)发生时不会发生冲突的 ID,我认为这可以通过 3 个步骤来实现:

Step 1

所有区域都将被分配整数 ID(唯一标识符):

  • 1 - 非洲;
  • 2 - 美国;
  • 3 - 亚洲;
  • 4 - 欧洲;
  • 5 - 大洋洲。

Step 2

为添加到集群的每个应用程序节点分配一个 ID,请记住,一个集群中可能最多有 99 999 台服务器(尽管我怀疑:只是作为一种安全预防措施)。这看起来像这样(假IP):

  • 00001 - 192.187.22.14
  • 00002 - 164.254.58.22
  • 00003 - 142.77.22.45
  • 等等。

请注意,所有这些都位于同一集群中,因此这意味着每个区域可以有节点 00001。

Step 3

对于插入数据库的每条记录,将使用递增的 ID 来标识它,这就是它的工作原理:

Couchbase 提供了一个增量功能,我们可以使用它在集群内部创建 ID。为了确保冗余,将在集群内创建 3 个副本。由于它们位于同一位置,因此我认为应该可以安全地假设,除非整个集群发生故障,否则负责此操作的节点之一将可用,否则可以增加多个副本。

将所有内容整合在一起

假设用户从欧洲注册: 服务请求的应用程序节点将获取区域代码(4在这种情况下),获得它自己的ID(比如说00005) 然后得到一个递增的 ID (1)来自 Couchbase(来自同一集群)。

我们最终得到 3 个组件:4, 00005,1。现在,要从中创建一个 ID,我们只需将这些组件加入到4.00005.1。为了让它变得更好(我对此不太确定),我们可以连接(不是将它们相加)最终得到的组件:4000051.

在代码中,这看起来像这样:

$id = '4'.'00005'.'1';

NB: Not $id = 4+00005+1;.

Pros

  • ID 看起来比 UUID 更好;
  • 它们看起来足够独特。即使另一个区域中的节点生成了相同的递增 ID,并且与上面的节点 ID 相同,我们也总是有区域代码来将它们分开;
  • 它们仍然可以存储为整数(可能是大无符号整数);
  • 这都是架构的一部分,没有增加复杂性。

Cons

  • 没有排序(或者有)?
  • 这是我最需要您的意见的地方

我知道每个解决方案都有缺陷,而且可能比我们表面上看到的还要多。您能发现整个方法有什么问题吗?

预先感谢您的帮助 :-)

EDIT

正如@DaveRandom建议的,我们可以添加第四步:

Step 4

我们可以生成一个随机数并将其附加到 ID 中以防止可预测性。实际上,你最终会得到这样的结果:

4000051357而不是仅仅4000051.


我认为这看起来很扎实。每个区域都保持一致性,如果您使用 XDCR,则不会发生冲突。 INCR 在集群中是原子的,因此不会有任何问题。您实际上不需要其中包含机器代码部分。如果一个区域内的所有应用服务器都连接到同一个集群,则中缀其中的 00001 部分是无关紧要的。如果这对您出于其他原因(某种分析)有用,那么无论如何,但这不是必要的。

所以它可以简单地是 '4' 。 1'(使用您的示例)

你能举个例子说明你需要什么样的“排序”吗?

First:添加熵的一个缺点(我不确定您为什么需要它)是您无法轻松地迭代 ID 集合。

例如:如果你的 ID 是从 1-100,你可以通过 Counter 键的简单 GET 查询知道,你可以按组分配任务,这个任务需要 1-10,接下来的 11-20 等等,工作人员可以执行在平行下。如果添加熵,则需要使用 Map/Reduce 视图来下拉集合,因此您将失去键值模式的好处。

Second:由于您关心可读性,因此添加文档/对象类型标识符也很有价值,这可以在 Map/Reduce 视图中使用(或者您可以使用 json 键来标识它)。

例如: 'u:' 。 ‘4’。 ‘1’

如果您在外部引用 ID,您可能需要以其他方式进行模糊处理。如果您需要一个示例,请告诉我,我可以在我的答案中附加您可以做的事情。

@scalabl3 http://twitter.com/scalabl3

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

建议的解决方案:在分布式环境中生成唯一 ID 的相关文章

随机推荐

  • np.fromfile 文件大小的最大限制?

    np fromfile 是否有最大文件大小 我正在尝试读取一个 48GB 文件 其中包含大约 2 1e9 条记录 每条记录有 5 个值 当我将计数限制为 8e7 时它起作用 fromfile filename dtp int 8e7 Out
  • 使用散点数据集生成热图

    我有一组 X Y 数据点 大约 10k 很容易绘制为散点图 但我想将其表示为热图 我查看了 Matplotlib 中的示例 它们似乎都已经从热图单元格值开始生成图像 有没有一种方法可以将一堆不同的 x y 转换为热图 其中 x y 频率较高
  • 在 React 中管理用户会话的最佳方法是什么?

    我对如何在 React 中管理用户会话有疑问 例如在 MVC NET 中 您只能使用 Session 对象 例如Session test 但显然 React 无法做到这一点 我正在阅读有关使用组件状态的内容 我认为在主要组件处设置状态并使用
  • Xcode Source Kit 将不会停止使用 Swift 崩溃[重复]

    这个问题在这里已经有答案了 我需要找到一个解决方案来解决 Swift 中超级棒的 Source Kit Crashing 错误 我读过很多堆栈溢出帖子 但似乎没有人有解决方案 如果有一行代码导致了问题 我不可能通过 50 多个源文件来找到它
  • 如何将字符串值从一个视图控制器传递到另一个视图控制器

    你好 我是目标 c 的新手 我有一个带有 h m xib 文件的登录视图控制器 成功登录后我需要转到第二页 场景是这样的 我正在访问网络服务 为了验证用户身份 我将用户名和密码发送到 Web 服务 作为回报我得到一个字符串值 根据字符串值的
  • 测量协议中的UserId、CID

    测量协议 为了识别新用户与回访用户 我们可以使用用户 ID 字段吗 即我们可以对用户名或其他用户唯一的标识符进行哈希处理 并将其与特定用户相关联 这样我们就可以有效地识别新用户与回访用户 关于 CID 的问题 CID 用于唯一标识用户的会话
  • EF6 与 Entity Framework Core:插入实体而不将主键(身份)重置为零

    EF6 插入已经具有主键值的实体可以正常工作 并向主键分配新值 EF Core 它尝试插入主键的值 但显然失败了异常 当 IDENTITY INSERT 设置为 OFF 时 无法在表 Asset 中插入标识列的显式值 我发现的解决方法是将
  • 如果没有 h3 标签,JQuery 手风琴将无法工作

    我正在尝试用 JQuery 制作手风琴 但遇到了一些麻烦 JQuery 网站显示如何创建您的手风琴内容 如下所示 div a href First header a div First content div a href Second h
  • 如何将数据访问映射到实体框架中的业务逻辑对象

    我在 ASP NET C MVC 应用程序中使用实体框架 我在数据访问层中有由 EF 生成的对象 namespace Project1 DataAccess using System using System Collections Gen
  • 如何在 jQuery Mobile 中检测设备的互联网连接

    我正在使用 HTML5 CSS3 jQuery Mobile jQuery UI ASP NET C 和一些 jQuery 插件为调查创建这个简单的移动网页 要求之一是显示一个弹出窗口 对话框 JavaScript 警报或 jQuery 移
  • 使用 Saxon 读取 XSLT 样式表中的环境变量

    我正在尝试生成一个 XML 文件 其中包含我的机器的主机名的任意元素或属性 例如
  • 通用类的通用父级

    我为此使用了一个虚构的例子 比如说 我有一个 Widget 类 例如 abstract class Widget Widget parent 现在 我的其他类将从这个 Widget 类派生 但假设我想在定义派生类型时在类中放置一些约束 以便
  • 如何在android上使用kso​​ap2调用WCF服务?

    这是我的代码 import org ksoap2 import org ksoap2 serialization import org ksoap2 transport import android app Activity import
  • 无法在PHP中的遍历预序中显示所有树

    我的数据库中有一个表 其中包含许多家谱树 id name parent id 1 grandfather NULL 2 father 1 3 uncle 1 4 son 2 5 brother 2 6 cousin s dauther 7
  • R 中随机森林的分层抽样

    我在文档中阅读了以下内容randomForest strata 用于分层抽样的 因子 变量 sampsize 要绘制的样本大小 对于分类 如果 sampsize 是一个长度为层数的向量 然后采样 按strata分层 sampsize的元素
  • 装饰器可以装饰递归函数吗?

    我想看看两种计算斐波那契数列的方法之间的时间成本差异 首先 我创建了一个装饰器 将 输出时间成本 函数添加到函数中 def time cost func def wed n start time time func n stop time
  • SQL依赖+服务代理

    我正在使用 SqlDependency 在某些表中的数据发生更改时获取通知 private void subscribeBroker using var conn new SqlConnection connString conn Open
  • 在Python中使用curses和raw_input

    在我的Python Linux控制台应用程序中 我使用curses来处理数据的显示 同时 我希望有一个输入行来输入命令 几乎是良好的 ol irssi 风格 使用默认的curses getch 我必须做大量的编码才能获得raw input函
  • 如何使 clang-format 尊重“类似表格”的代码格式

    我的代码具有按列对齐的数据或参数表 如下所示 人为的简单示例 实际代码具有更大的表 Name Size Starting val S s Dubs abc 123 X n m YZ ij q kl Name Size Starting va
  • 建议的解决方案:在分布式环境中生成唯一 ID

    我一直在浏览网络 试图找到一种解决方案 使我们能够在区域分布式环境中生成唯一的 ID 我查看了以下选项 除其他外 雪花 推特 这似乎是一个很棒的解决方案 但我只是不喜欢仅仅为了创建 ID 而必须管理另一个软件所带来的额外复杂性 现阶段缺乏文