Database design 如何在最终的一致性环境中保留唯一的值?

Database design 如何在最终的一致性环境中保留唯一的值?,database-design,eventual-consistency,Database Design,Eventual Consistency,是否有人有任何关于如何在最终一致的环境中进行独特价值保留的链接/资源 示例:用户在注册时可以选择自己的用户名。即使两个用户试图同时获取相同的名称,也只有一个用户会成功 我脑子里有几个潜在的解决方案,但我想知道是否有人已经为这个设计做了准备。当你提到用户名字段时,你让我想起了一个老的病毒性笑话,它说50年后人类必须解决的最大问题是在互联网上找到一个可用的用户名 您在评论中提到的问题与锁定和并发插入有关,详情如下: 现在,据我所知,insert语句在执行之前被缓存并存储在队列中,而不管它们到达的时间

是否有人有任何关于如何在最终一致的环境中进行独特价值保留的链接/资源

示例:用户在注册时可以选择自己的用户名。即使两个用户试图同时获取相同的名称,也只有一个用户会成功


我脑子里有几个潜在的解决方案,但我想知道是否有人已经为这个设计做了准备。

当你提到用户名字段时,你让我想起了一个老的病毒性笑话,它说50年后人类必须解决的最大问题是在互联网上找到一个可用的用户名

您在评论中提到的问题与锁定和并发插入有关,详情如下:

现在,据我所知,insert语句在执行之前被缓存并存储在队列中,而不管它们到达的时间如何。因此,一个会自动获得唯一值(例如:用户名),而另一个不会。但实际上,两个用户在同一个原子时间选择同一用户名的几率非常非常低。即使是在实验室环境中,也有很多东西需要完美地工作才能进行测试

另一方面,您可以允许两个用户在拥有相同用户名的情况下注册。例如:假设您有一个用户帐户系统,允许用户使用用户名和密码注册。用户名限制为以下字符:a到z、a到z、0到9加上特殊字符u(下划线)和(句号)。您可以将用户名(在mysql表中定义为非唯一)与一个特殊字符(除u和)连接起来,后跟mysql表中的唯一标识符(比如用户id)

当用户尝试登录时,您将其输入与所有子字符串用户名集进行比较(您只获取定义的特殊字符之前的值)。在数组中记录匹配项,然后检查用户密码是否与找到的任何用户密码匹配。如果有,你就让他登录,如果没有,你就没有


虽然我在实践中看到了上述情况,但我非常反对。我会使用用户的电子邮件,而不是唯一的用户名。这是一个更简单、更干净的解决方案,因为电子邮件是独一无二的。没有两个用户拥有相同的电子邮件帐户,除非他们共享该地址(例如,听起来像contact@xyzcompany.com).

唯一性约束要求可序列化/线性化。这使得它不可能在非序列化系统中实现。CAP意义上的所有AP系统都是不可序列化的

最终的一致性定义模糊,但它几乎意味着一个不可序列化的系统因此,您的请求无法实现。


选择一个一致的数据库,以获得所需的唯一性保证,并可能将该数据复制到最终一致的数据存储中。

这是理论答案非常愚蠢的问题之一。 是的,任何唯一标识符都需要某种形式的序列化

但在现实世界中,很容易扩展现有的唯一标识符以形成新的唯一标识符。最明显的是您机器的公共IP地址和时间戳。在任何时候,一个IP地址只能有一个所有者,因此该组合是唯一的。现在,您只需决定允许从一个节点创建多少条时间戳精度的记录


域名也有同样的特点,但不那么紧凑。但它们更容易验证,这就是为什么它们通常用于为对象类形成真正的全局名称空间。

我不同意。在最终一致的环境中,您最终可以保证唯一性。一种方法是使用某种两阶段系统,包括等待一致性窗口。我在想象一种预订/预订确认模式。。。我只是想知道是否有人已经发布了类似的东西。那么,预订确认必须是一致的。。。如果您要求系统各方同意一个用户名,则需要协调每个人。据报道,这是不可能实现的。请参阅“aphyr”(搜索该名称)的工作。精彩的文章。这是一个复杂的话题。另一个评论是:如果你能保证在有限的时间内获得一致性,我相信这是可能的。但是你的系统不再可用或一致,因为你不能容忍任意的消息丢失(在任意的持续时间内)。。。在第一阶段,我向列表/队列/whateverIHaveAccessTo添加一个预订请求。在第二个阶段,只有在一个时间窗口之后才能运行,在这个时间窗口中,我们可以确保列表/队列/内容的一致性,我们可以查看我的请求是否是“获胜”的请求,如果是,我可以使用有争议的内容(用户名?),如果我不是获胜的请求,我必须选择一个新的请求。您完全错过了“最终一致”是问题的一部分。