Database 检查一个数字是否存在于多个集合中而不搜索所有集合的好算法是什么?

Database 检查一个数字是否存在于多个集合中而不搜索所有集合的好算法是什么?,database,algorithm,math,sharding,discrete-mathematics,Database,Algorithm,Math,Sharding,Discrete Mathematics,场景 假设您在3个区域中有多个数据库。分区A、B和C。每个区域位于不同的地理位置。同时,您有一个应用程序,它将根据用户的地理位置路由用户名和密码。例如,用户A将被重定向到区域A中的数据库。用户B区域B等等 现在,假设用户A移动到区域B。应用程序查询区域B,将找不到任何内容。查询区域A和区域C可能需要一些时间,因为区域距离较远,并且必须查询所有区域中的所有数据库 我的问题 如何验证一个字符串/数字是否存在于多个集合中 或 在发送查询之前,如何验证数据库中是否存在行 我的算法 这并不完美,但会让你知

场景

假设您在3个区域中有多个数据库。分区
A
B
C
。每个区域位于不同的地理位置。同时,您有一个应用程序,它将根据用户的地理位置路由用户名和密码。例如,用户
A
将被重定向到区域
A
中的数据库。用户
B
区域
B
等等

现在,假设用户
A
移动到区域
B
。应用程序查询区域
B
,将找不到任何内容。查询区域
A
和区域
C
可能需要一些时间,因为区域距离较远,并且必须查询所有区域中的所有数据库

我的问题

如何验证一个字符串/数字是否存在于多个集合中

在发送查询之前,如何验证数据库中是否存在行

我的算法

这并不完美,但会让你知道我在做什么

如果我们有以下3个用户的数据库

  • 酒吧
  • 福巴
我们获取所有3个用户的散列,如果散列不是素数,则查找下一个素数

sum = hash(foo).nextPrime() * hash(bar).nextPrime() * hash(foobar).nextPrime()
该总和在所有分区之间共享。如果我想检查
foo
,我可以只取foo的散列,并查找下一个素数,然后取
gcd(foo,sum)
。如果它不等于一。这意味着foo存在于某个数据库中。如果它等于1,则表示foo根本不存在。如果我想添加一个新用户名。我只需做
sum=sum*hash(newUserName).nexttime()。

Sum将增长到查询所有数据库的速度更快的点


您知道解决此问题的类似算法吗?

适合此应用程序的一种数据结构是

Bloom筛选器是一种概率数据结构,允许您测试项目是否已在集合中。如果测试返回false,则该项目肯定不在集合中(0%假阴性),如果为true,则该项目可能在集合中,但不保证在集合中(可能出现假阳性)

该滤波器被实现为具有m个比特和一组k个散列函数的比特数组。要将项目添加到数组中(例如用户名),请使用每个哈希函数对项目进行哈希,然后取每个哈希值的模m,以计算要在位数组中设置的索引。要测试一个项是否在集合中,请计算所有哈希和索引,并检查数组中的所有对应位是否都设置为1。如果其中任何一项为零,则该项肯定不在集合中,如果所有项都为1,则该项最有可能在集合中,但很可能不在集合中,通过使用较大的m,可以降低误报的百分比

为了实现k个散列函数,可以只使用相同的散列算法(例如CRC32、MD5等),但在传递到散列函数之前,为每个函数的用户名字符串添加不同的salt,从而有效地为每个salt创建“新”散列函数。对于给定的m和n(添加的元素数),哈希函数的最佳数目是k=(m/n)ln2

对于您的应用程序,Bloom过滤器位阵列将在所有区域A、B、C等之间共享。当用户尝试登录时,您可以首先检查本地区域的数据库,如果存在,然后正常登录。如果本地数据库中不存在,请检查Bloom筛选器,如果结果为负,则您可以确定它们不存在于其他区域中。如果是肯定的,那么您仍然需要检查其他区域中的数据库(因为可能存在误报),但这大概不是一个大问题,因为如果是真的肯定,您将在任何情况下联系其他区域来传输用户的数据


使用Bloom过滤器的一个缺点是,一旦添加了元素,就很难从集合中删除它们。

考虑使用Bloom过滤器@samgak,这正是我想要的。如果你对算法做了很好的解释,我会把你的答案标记为正确。