database - 按 user_id 与按 entity_id 分片数据库

标签 database database-performance sharding high-availability

我现在的员工有一个很大的项目表。每个项目都有 user_id 和明显的 item_id 属性。为了提高性能和高可用性,我的团队决定对表进行分片。 我们正在讨论两种策略:

item_id 分片

就高可用性而言,如果分片出现故障,那么所有用户都会临时丢失 1/N 的项目。性能将在所有分片上均匀(随机分布)

user_id 分片

如果分片出现故障,则 N 个用户中有 1 个将无法访问他们的项目。性能甚至可能不是因为我们有拥有 1000 件元素的用户以及只有一件元素的用户。此外,还有一个很大的缺点 - 现在我们需要传递 item_id 和 user_id 才能访问项目。

所以我的问题是 - 选择哪一个?也许你可以用一些数学公式来指导我来决定在不同情况下哪个更好

附言我们已经有了副本,但它们对我们的写入吞吐量变得毫无用处

更新

我们有 serp 页面,我们需要通过 ID 获取项目,以及用户想要查看他/她的项目的用户个人资料页面。与第二个不同,第一个模式是最常用的。 我们可以很容易地放弃 ACID 事务,因为我们已经开始构建微服务(因此最终几乎所有大型实体都将封装在特定的微服务中)。

最佳答案

我看到了几种攻击方法:

  • 你打算如何分片?独立的主服务器,独立的模式 由同一台服务器提供服务,但由不同的存储后台提供服务?
  • 您如何访问这些数据?它基本上是键/值吗?您是否需要一次查询用户的所有项目?您的 CRUD 操作需要具备怎样的事务性?
  • 根据您存储的数据,您是否预见到分片不平衡会成为一个问题?
  • 您是否需要针对其他数据对该数据进行关系查询 在你的系统中?

权衡

  • 如果您跨服务器/数据库实例边界拆分分片,按 item_id 分片意味着您将无法对有关单个 user_id 的信息进行单个查询。 . 您将需要查询每个分片,然后在应用程序级别聚合结果。我发现聚合的陷阱比你想象的要多得多……最好将其保存在数据库中。
  • 如果您可以使用单个数据库实例,通过创建由不同存储子系统支持的表/模式进行分片将允许您扩展写入,并且仍然能够跨它们进行关系查询。不过,使用这种方法,您所有的鸡蛋仍然在 1 个服务篮中。
  • 如果您按 user_id 进行分片,并且您希望通过将用户移动到另一个分片来重新平衡您的分片,您将需要一次原子地移动所有用户的行。如果有很多行,这可能会很困难。如果按 item_id 进行分片,则一次可以移动一个项目。这允许您逐步重新平衡您的分片,这非常棒。
  • 如果您打算将它们拆分到单独的服务器中,这样您就无法跨模式进行关系查询,那么使用键/值存储作为 DynamoDB 可能会更好。然后你只需要担心一个端点,分片是在数据库层完成的。没有中间件来确定使用哪个分片!

关键权衡似乎是查询所有特定用户数据的能力(按 user_id 分片)与跨分片的数据更容易平衡和重新平衡(按 item_id)。

我将重点关注您需要如何存储和访问数据的问题。如果您确实只需要通过 item_id 进行访问,则可以通过 item_id 进行分片。避免以与查询方式适得其反的方式拆分数据库。

如果您仍然不确定,请注意,您可以按 item_id 进行分片,然后选择按 user_id 进行分片(您可以通过基于 的重新平衡来完成此操作>user_id 然后强制新行只写入其 user_id 所属的分片。

根据您的更新,听起来您主要关心的不是关系查询,而是扩展写入到这个特定数据池的操作。如果是这种情况,按 item_id 进行分片可让您最灵活地随时间重新平衡数据,并且不太可能产生热点或一开始就变得不平衡。这是以必须跨分片聚合基于 user_id 的查询为代价的,但只要那些“给定用户的所有项目”查询不需要一致性保证,你应该没问题。

关于database - 按 user_id 与按 entity_id 分片数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49784092/

相关文章:

database - 对 uuid 进行模运算以确定 shard_id

nosql - 分片与 DFS

mysql - 创建另一个表只是为了存储一些选项?

java - 无法使用 Android 连接到数据库

sql - 在 F# 中重播记录的数据流

javascript - 如何从 Node.js 快速将许多脚本生成的记录放入 PostgreSQL 中?

mysql - 在mysql中将时间乘以十进制值?

mysql - 如何在cassandra和mysql之间做性能测试?

performance - 在 MongoDB 中批量插入的最高效方法

mysql - 需要帮助选择正确的 mysql 数据库分片、集群或分区方法