代码之家  ›  专栏  ›  技术社区  ›  Nicholas Knight

通过哈希将用户(或其他任何内容)分发到数据库服务器

  •  1
  • Nicholas Knight  · 技术社区  · 15 年前

    我正在为一个应用程序进行早期设计,这个应用程序需要从小处开始,但具有很高的可扩展性。我特别担心用户数据库,在本例中,它将具有很高的插入和更新负载,并且不太可能在单个主服务器上长期存在。

    (尽管我的问题与任何特定的RDBMS都没有关系,但是我们会使用MySQL,而且MySQL集群并不能真正满足我们的需求,所以我们需要使用stock mysql+innodb在这个上面滚动我们自己的解决方案。)

    我正在考虑一种基于用户名散列值在MySQL主服务器之间分配用户的策略(加上一个用户未知的salt,就像增加了防止任何有趣游戏的保险一样)。我以前见过这样的解决方案成功地使用过,但我自己从未设计/实现过它。

    我想要的是:

    1)合适的哈希算法。我希望sha-1或者甚至md5可以很好地解决这个问题,因为加密安全并不是我们的目标,但是我不确定是否还有其他的算法可以解决这种问题。再快一点也许也不错。

    2)任何人都能想到的重大警告。(我已经) 非常 意识到潜在的连接池问题,以及在池中添加新的主控形状和迁移受影响的用户时的乐趣。)

    谢谢!

    2 回复  |  直到 15 年前
        1
  •  2
  •   blowdart    15 年前

    基于哈希的解决方案的问题是移动用户。考虑下面的场景-您有3个用户和3个服务器。用户A有一个散列值,导致其连接被您的软件分配给服务器A,用户B连接到服务器B,用户C连接到服务器C。如果服务器B停机,或者您希望将用户B迁移到新的服务器D,因为服务器B超载-您不能,因为您的软件被编码为获取用户名散列值,并基于此连接到服务器。

    另外,您也会遇到分发问题——用户A、B和C的散列可以很好地解析为服务器A,因此服务器B和C处于空闲状态。

    我个人会在所有服务器之间复制用户数据库表,然后在启动时随机连接到一个服务器,找到他们实际的数据库服务器,然后在这一点上继续。这样您就可以轻松地移动用户,并且,如果您在至少两个服务器之间复制数据,那么在服务器崩溃时,您就有了冗余。

        2
  •  2
  •   SquareCog    15 年前

    首先,我觉得有责任告诉你,如果你足够认真地考虑设计的话,你可能不需要把它分了。切分是最后的手段。下面是珀科纳的斯瓦茨男爵谈到的(不要错过幻灯片的直接链接): http://www.percona.tv/performance/baron-schwartz-high-performance-mysql-from-a-boring-architecture-ppc-2009

    根据实际的建议。

    要考虑的一件事是如何重新平衡应用程序。您从3个节点开始;在某个时刻添加第四个节点。如何迁移四分之一的数据?通过重新刷新每个用户?可能是个坏主意。要考虑的一件事是将模式划分为多个编号的模式,并将模式编号散列到数据库机器上。这样,您就可以通过只移动需要触摸的模式进行迁移,而不是重新刷新所有数据。因为模式的数量(数量)大于机器的数量,所以您也不能依赖散列来查找数据库机器,而是使用可以为迁移更新的静态映射。这样,如果您的一些用户比其他用户活跃得多,并且创建了一个歪斜,那么您也可以使用每台机器模式的非均匀分布——您可以手动重新分配负载,以便更好地工作。

    您仍然需要将用户映射到模式。我一直在阅读的一个有趣的方法不是散列到桶中,而是使用 散列函数将散列到2个存储桶,并选择两个存储桶中加载最少的(由用户、记录或其他度量)作为目标。这会导致更为均匀的分布,但当需要为用户取回数据时,会导致检查这两个分布的开销。这可以通过缓存减轻,但仍然如此。不过,还是要考虑一下。

    您可能需要考虑复制这些碎片——可能是异步的,作为后台进程,用于热备份。

    最后,您考虑过替代技术吗?各种大表克隆虽然不提供关系模型,但在读写方面具有非常好的伸缩特性。退房 Cassandra HBase .