微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

有没有一种方法可以确保字段的唯一性而不依赖数据库

如何解决有没有一种方法可以确保字段的唯一性而不依赖数据库

无需,就无需依赖数据库,就可以确保一个字段(例如,用户emailAddress)是唯一的。

一些常见的失败尝试:

  1. 首先检查emailAddress是否存在(通过查询数据库),如果不存在,则创建用户。现在,很明显,在“先检查后执行”窗口中,其他线程可以创建具有相同电子邮件用户。因此,这种解决方案不好。
  2. 在负责创建用户方法上应用语言级别的锁定。该解决方案失败了,因为出于性能原因我们需要服务的冗余,并且锁定位于单个JVM上。
  3. 使用事件存储区(例如Akka参与者的邮箱),事件是AddUser消息,但是由于参与者的行为是异步的,因此无法通知请求者(发送者)使用唯一电子邮件成功创建用户。此外,两个请求(使用相同的电子邮件)如何知道它们包含唯一的电子邮件?这可能会变得复杂。

数据库是每个线程和每个服务实例将写入的单一数据源,因此在此处实现unique constraint很有意义。但这对于关系数据库仍然适用。 那 Nosql 数据库呢?有些确实允许一个唯一的约束,但这不是他们的本机行为,或者也许是。

但是不使用数据库实现字段唯一性的问题是,可能有什么选择?

解决方法

我认为您的问题更为笼统-“如何确保数据库写入操作成功完成,以及如何处理未成功的情况?”。唯一性只是一种失败模式-您可能试图插入一个太大的值,错误的数据类型或与外键约束不匹配的值。

关系数据库通过符合ACID的要求来解决此问题,并在事务失败时引发错误以供客户端处理。

您需要ACID的(部分)好处,而无需关系数据库。那是相当大的topic对话。解决此问题的明显方法是在应用程序层中引入“事务”的概念。例如,在您的情况下,您可能会发送“创建帐户(emailAddress,名称,...)”消息,并让应用程序侦听“ accountCreated”或“ accountCreationFailed”响应。该消息的接收者负责写入数据库;您有两种选择。一种是锁定该线程(因此任何时候任何一个进程都只能写入数据库)。那不是超级可扩展的。我使用的另一种机制是引入状态标志-您使用“草稿”标志将帐户数据写入数据库,然后检查您的约束条件(包括唯一性),如果将“草稿”标志设置为“已验证”满足约束条件(即没有其他记录具有相同的电子邮件地址),如果没有,则“失败”。

,

要检查唯一性,您需要存储程序的“状态”。为了安全起见,您需要能够以事务方式将更改应用于状态。

  • 您可以使用数据库事务。一些NoSQL数据库也支持事务,例如redis和MongoDB。您必须分别检查每个供应商,以了解他们如何支持交易。在此设置中,每个客户端都将连接到数据库,它将为您处理所有详细信息。另外,根据您的用例,您应该注意隔离级别的配置。
  • 如果不考虑持久性,则可以在支持事务的内存数据库中使用。

选择哪个状态存储,它应该支持事务。有几种方法可以实现事务并实现一致性。许多类似PostgresSQL的关系数据库都是通过实现MVCC算法来实现的。在分布式环境中,您必须查找诸如2PC,Paxos等的分布式事务。

通常每个人都依赖可用的数据存储解决方案,除非对该项目有奇怪或特定的要求。

最后,沟通模式与这里的潜在问题无关。例如,在您提到的Actor案例中,一天结束时,每个actor都必须查询状态以查找是否存在电子邮件。如果您的状态存储支持Serializability,则不会有问题,也不会发生冲突(将错误传达给客户端是另一个问题)。假设您正在使用PostgreSQL。发出插入/更新查询时,它将包裹在事务中,并且底层MVCC算法将处理所有事务。在高级且分散的环境中,您可以使用支持分布式事务的数据存储,例如CockroachDB。

如果您想深入研究,可以研究以下关键字:ACID,隔离级别,原子性,可序列化性,CAP定理,2PC,MVCC,分布式transaciton,分布式锁,...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。