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

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

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

雪花(Twitter)

看来这是一个很好的解决方案,但我只是不喜欢必须管理另一个软件才能创建ID所增加的复杂性。
它在现阶段缺少文档,所以我认为这不是一个很好的投资。
节点需要能够使用Zookeeper相互通信(延迟/通信失败是什么?)

UUID

看看吧:550e8400-e29b-41d4-a716-446655440000;
它是一个128位ID;
发生了一些已知的冲突(取决于我猜的版本)see this post。

像MySQL一样在关系数据库中自动增加

这似乎很安全,但是不幸的是,我们没有使用关系数据库(可伸缩性首选项)。
我们可以像Flickr一样为此部署MySQL服务器,但是同样,这又引入了另一个故障点/瓶颈。也增加了复杂性。

像库奇这样的非关系数据库中的自动增量

因为我们使用Couchbase作为数据库服务器,所以这可能有效。
当我们在不同区域中有多个群集,延迟问题,网络故障时,这将不起作用:在某些时候,ID会根据流量的多少而发生冲突。

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

可以说,我们有5个不同区域(非洲,欧洲,亚洲,美洲和大洋洲)中的10个Couchbase节点和10个Application节点组成的集群。这是为了确保从最接近用户的位置提供内容(以提高速度),并确保在发生灾难等情况下实现冗余。

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

第1步

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

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

第2步

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

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

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

第三步

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

Couchbase提供了增量功能,我们可以使用该功能在集群内部内部创建ID。为了确保冗余,将在群集内创建3个副本。由于这些文件位于同一位置,因此我认为可以肯定地假设,除非整个集群都关闭,否则负责此操作的节点之一将可用,否则可以增加许多副本。

汇集全部

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

我们最终得到3个组成部分:4, 00005,1。现在,要从中创建一个ID,我们只需将这些组件连接到4.00005.1中即可。为了使其变得更好(我不太确定),我们可以将组件串联(而不是将它们加起来),最后得到:4000051

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

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

注意:不是$id = 4+00005+1;

优点

ID看起来比UUID好;
它们似乎足够独特。即使另一个区域中的一个节点生成了与上面相同的递增ID,并且具有与上述相同的节点ID,我们也始终具有将它们分开的区域代码。
它们仍然可以存储为整数(可能是Big Unsigned integer);
这都是架构的一部分,没有增加任何复杂性。

缺点

没有排序(或没有排序)?
这是我需要您输入的地方(大部分)

我知道每种解决方案都有缺陷,而且可能还存在着表面上的缺陷。您能发现整个方法有什么问题吗?

预先感谢您的帮助 :-)

编辑

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

第4步

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

4000051357,而不只是4000051

参考方案

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

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

您能给我一个例子,说明您需要哪种“分类”吗?

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

例如:如果您的ID是1-100,您可以通过对Counter键进行简单的GET查询来知道ID,则可以按组分配任务,此任务需要1-10,接下来的11-20,依此类推,并需要工人可以并行执行。如果添加熵,则将需要使用“映射/缩小视图”来拉下集合,因此您将失去键值模式的优势。

第二:由于您关注可读性,因此添加文档/对象类型标识符也很有价值,并且可以在“地图/缩小视图”中使用它(或者您可以使用json键来识别它)。

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

如果您是从外部引用ID,则可能希望以其他方式掩盖。如果您需要一个例子,请告诉我,我可以在回答中附加您可以做的事情。

@scalabl3

PHP-将日期插入日期时间字段 - php

我已在数据库中使用datetime字段存储日期,使用PHP将“今天的日期”插入该字段的正确方法是什么?干杯, 参考方案 我认为您可以使用php date()函数

PHP-如何获取类的成员函数列表? - php

如果我知道班级的名字。有没有办法知道类的成员函数列表? 参考方案 get_class_methods()是你的朋友

php ziparchive类源代码 - php

Improve this question 我如何获取ziparchive类本身的源代码。 参考方案 假设您在谈论PHP ZipArchive class:下载PHP source code并查找适当的文件。如果您希望源代码是PHP代码,您可能会感到失望,因为源代码是用C语言编写的。或者,也可以在PHP Github Development Reposito…

PHP getallheaders替代 - php

我正在尝试从服务器上的apache切换到nginx。唯一的问题是我在PHP脚本中使用的getallheaders()函数,该函数不适用于Nginx。我已经尝试过用户在getallheaders函数上的php站点上提供的注释,但这并不返回所有请求标头。请告诉我如何解决这个问题。我真的想切换到Nginx。 参考方案 您仍然可以使用它,但是您必须像这里一样重新定义…

PHP-如何建议搜索字词,“你是说……?” - php

当使用不检索任何结果的术语搜索数据库时,我想允许“您是不是……”建议(例如Google)。例如,如果有人寻找“ jquyer””,它将输出“ did you mean jquery?”当然,建议结果必须与数据库内部的值匹配(我正在使用mysql)。您知道可以做到这一点的图书馆吗?我已经用谷歌搜索过,但是没有找到任何好的结果。或者,也许您有一个想法,该如何独自…