我有很多用户数据。每个用户都有一个唯一的用户 ID,由 6 个字符的 Base64 表示。例如(Fga6=gY)。 我使用哈希函数将用户分散到我的 MySQL 机器上。
我有四台机器,所以当我想保存新用户时,我只需检查应该保存哪个服务器:
hash(userId) % 4
我的问题是,如果 4 台机器负载过多,如何添加更多机器。 如果我开始使用 6 台机器并使用模 6 而不是 4,它将适用于新用户。但是当尝试查询旧用户时,我的应用程序服务器将被转发到错误的机器。
对于已经投入生产的系统如何解决这个问题?
如何更好地规划系统,以便我可以在需要时扩展机器?
太糟糕了,你在实现那个简单的哈希之前没有问过。
第一我强烈建议编写一个脚本将一个用户从一个分片移动到另一个分片。 它将成为以下大部分建议的重要组成部分。
哈希的替代品“字典查找”是指在表中列出用户以及他们所在的分片。 这允许将单个用户从一个分片移动到另一个分片。 (这种“移动”的细节可能相当复杂。)这可以实现多种好处:将一些用户从繁忙的服务器移动到不太繁忙的服务器;添加新分片;配备新分片,然后将用户转移到新服务器。 等等
“字典”和“哈希”之间的折衷方案如下:将 user_id 哈希为 512 个可能的值。 然后使用仅包含 512 个条目的字典来查找这些用户所在的分片。 这需要移动一组用户,而不仅仅是单个用户,但保持字典大小固定。
无论哪种情况,都需要将“字典”传播到所有客户端以供他们使用。
小帮助重新散列基本上涉及移动所有数据。 这对于停机来说是相当昂贵的。 相反,请思考这一点。 哈希模 8(具体为 2*4)。 然后将
one分片分成两个服务器。 这只会给 1/4 的用户带来痛苦。 实际上,使用“移动一个用户”脚本,只有 1/8 的用户会受到影响。 当然,客户端中有一定数量的代码来了解某些分片拥有 1/4 的用户;有些有1/8。 (这会引导您从 4->8,而不是您要求的 4->6。)
替代拓扑如果您的客户端与分片位于同一服务器上,请考虑将应用程序代码移动到其他服务器上。 即数据库分片上只有MySQL;其他服务器上还有其他东西。 如果需要,可以对它们进行不同的配置(RAM、IOP 等)。 您的系统实际上可能需要多于 4 台或少于 4 台客户端计算机来处理相关负载。 这种拓扑允许单独缩放每个。
优化你是否开启了慢日志?
long_query_time
的值较低? 针对该日志运行
pt-query-digest
。 然后,让我们讨论前几个查询。 他们“可能”跑得比应有的速度慢。 https://mysql.rjweb.org/doc.php/mysql_analysis#slow_queries_and_slowlog这可能会让您推迟添加分片。