这是一般设计问题 - 我想在用户输入值并标签输出时验证用户名字段的唯一性。我进行Ajax验证并从服务器获得响应。这都非常标准。现在,如果我有一个巨大的用户数据库怎么办?如何处理这种情况?我想知道在150万个用户名中是否存在用户名“foozbarz”?
或者,还有其他更好的方法吗?
答案 0 :(得分:2)
为什么不简单地对数据进行分区?如果你有/计划拥有150M +用户,我认为你已经/将有预算。如果您刚刚开始(使用2k用户),请使用简单的数据库索引搜索方式。如果您有这么多用户观察性能问题而衡量这是因为您的数据库(而不是例如www服务器),那么您只需添加另一个数据库。在第一个上,您将拥有名称从a到m的用户,并在另一个上休息。您可以选择其他标准,如哈希,以使数据平衡。当您需要更多时,您将添加更多数据库。但如果你现在没有这么多用户,我建议你不要做任何过早的优化。有很多事情可能成为这一数据量的瓶颈
答案 1 :(得分:1)
你最有可能在存储所采用的名称时进行某种散列,显然,不散列意味着它是免费的。
您不应该做的是依靠该验证。如果名称是免费的,用户按下注册和用户检查之间可能会有很多时间。
公平地说,这里只有一个问题,你是否真的需要担心你是否会获得1.5亿用户。可伸缩性通常是一个问题,但除非这种情况发生在一夜之间,否则在发生这种情况之前,您可能会交换更好的解决方案。
其次,您担心这两个用户获得此名称是免费的,然后一个人接受它。首先,发生这种情况的可能性非常低。其次,我可以想到以一种方式“解决”这个问题的唯一方法,即用户永远不会点击确认并使用经过验证的名称并获得USERNAME TAKEN a)记住用户最后验证的内容,存储该内容,以及如果其他人同时注册该内容,请使用AJAX更改要采用的名称字段并通知用户。不要这样做。许多浪费的周期和实施太多的努力。 b)锁定用户名作为用户在短时间内验证一个用户名。这导致很多免费用户名在实际上没有时就会出现。你可能也不想要这个。
最简单的解决方案是在用户实际单击“确定”时简单地将哈希值放入表中,但在此之前,请检查名称是否再次存在。如果是这样,只需用USERNAME TAKEN发回用户。有人为别人争取名字的可能性非常非常小,我怀疑任何人都会对你的验证员(做了它的工作,这个名字在检查时是免费的)如何对用户“撒谎”大惊小怪
基本上,您唯一的问题是如何存储昵称。
答案 2 :(得分:1)
您的#1标准存在缺陷,因为这正是您拥有的数据库系统:存储和管理数据。如果你不打算阅读它,为什么你甚至有一个带有用户名的表呢?
首先要做的是通过添加索引来改进数据库系统,如果您的数据库系统支持索引,最好是HASH
索引。你将很难在自己的表现附近写任何东西。
如果这还不够,则必须开始扩展数据库,例如通过构建集群数据库或将表分区为多个子表。
我认为公平的做法是在数据库前实现缓存,但对于单个名称。并非所有用户名都会发生冲突尝试,因此您可以缓存通常发生冲突的小子集。用于检查USER的碰撞状态的简单算法:
当然,您仍需要在数据库中使用UNIQUE约束来避免竞争条件。
答案 3 :(得分:0)
如果您要使用传统路由,则可以使用适当的索引来改进数据库查找。
你也可以尝试使用像ElasticSearch这样的东西,它对大型数据集进行非常低的延迟查找。
答案 4 :(得分:0)
如果您有150M +用户,则必须具备以下功能:
你将遇到这个问题,并且必须解决它。很可能与某个用户的查询相似。即使你非常依赖会话,你仍然会遇到“从150M +池中找到许多会话X”的问题,这在结构上与“从150M +池中找到许多用户X”相同。
一旦你解决了更大的问题,你现在遇到的问题只是步骤#1。
因此,我将查看可扩展的数据库解决方案(可能是NoSQL解决方案),并使用该解决方案实现“可用性检查”。
您可能会以
结尾retrieveUserData(user, password = None)
如果用户和密码有效且正确,则返回用户信息。对于可用性检查,您将不发送密码,并且如果用户名可用,则会出现UserNotFound异常。