我有很多用户的数据。每个用户id都有一个唯一的用户id,它由一个由6个字符组成的base64表示。例如(Fga6=gY)。我使用哈希函数将用户分散到我的MySQL机器上。
我有四台机器,所以当我想要保存一个新用户时,我只需要检查应该保存它的服务器:
hash(userId) % 4我的问题是,如果我在4台机器上有太多的负载,我如何增加更多的机器。如果我开始使用6台机器,并使用模块化6而不是4,它将为新用户工作。但是,当试图查询老用户时,我的应用程序服务器将被转发到错误的计算机。
对于一个已经投入生产的系统,我如何解决它呢?
我怎样才能更好地规划一个系统,使我能够在需要时扩大机器的规模?
发布于 2021-06-20 04:46:32
不幸的是,在实现这个简单的散列之前,您没有问。
First
我强烈建议编写一个脚本将一个用户从一个碎片移动到另一个碎片。这将是大部分以下建议中的一个重要组成部分。
哈希的替代方案
“字典查找”是指在表中列出用户的位置,以及他们所使用的碎片。这允许将单个用户从一个碎片移动到另一个碎片。(这种“搬迁”的细节可能相当复杂。)这允许各种好的东西:将一些用户从繁忙的服务器转移到不那么繁忙的服务器;添加一个新的碎片;安装一个新的碎片,然后将用户移动到新的服务器。等。
“字典”和“哈希”之间的折衷方法如下:将user_id散列为512个可能的值。然后使用一个只有512个条目的字典来查找那些用户正在使用的碎片。这需要移动一组用户,而不仅仅是单个用户,而是将字典保持在固定大小。
在任何一种情况下,“字典”都需要传播到所有客户端,以便他们使用。
小帮手
重新哈希实际上涉及到移动周围的所有数据。这在停机时间是相当昂贵的。相反,好好思考一下。散列模式8(特别是2*4)。然后将一个碎片分成两个服务器。这只会给1/4的用户带来痛苦。实际上,使用“移动一个用户”脚本,只有1/8的用户会受到影响。当然,客户端中有一定数量的代码来理解一些碎片有1/4的用户,有些则有1/8的用户。(这导致你从4->8,而不是你所要求的4->6。)
替代拓扑
如果客户端与碎片位于同一服务器上,请考虑将应用程序代码移到其他服务器上。也就是说,数据库碎片上只有MySQL;在其他服务器上有其他东西。并根据需要对它们进行不同的配置(RAM、IOP等)。您的系统可能实际上需要超过4台或少于4台客户端机器来进行负载。此拓扑允许对每个拓扑分别进行缩放。
优化
你打开慢速日志了吗?long_query_time的值很低?对该日志运行pt-query-digest。然后,让我们讨论前几个查询。他们可能跑得比他们可能要慢。http://mysql.rjweb.org/doc.php/mysql_analysis#slow_queries_and_slowlog
这可能会让您推迟添加碎片。
https://stackoverflow.com/questions/68016845
复制相似问题