2

我没有横向扩展 SQL 后端的经验,但从我目前所读的内容来看,写入分片和读取缓存似乎是两种最常见的做法。我正在尝试了解如何使用正确的缓存策略来最小化最终的一致性。

我想使用 Azure SQL 数据库、Entity Framework & Elastic Sc​​ale 中间件和 Redis 进行测试。

有没有办法同时向 SQL Server 和 Redis 提交分布式事务?

如果不是,那么在发生数据库更改时确保读取新鲜度的有效方法是什么?

我可以在同一个 API 中写入 SQL 并更新缓存,但写入缓存可能会因任何原因而失败。我可以实现重试逻辑,但假设所有尝试都失败,我可以尝试回滚 SQL 事务或简单地将旧缓存数据提供给客户端并定期重建缓存以赶上数据库。当然,后者意味着数据读取在一段时间内不一致。驱逐数据并从 SQL 集群读取是另一种选择,但跨分片查询可能非常昂贵,尤其是当它们涉及复杂的连接并且您在商品硬件上拥有数百个(如果不是数千个)数据库时。

4

2 回答 2

1

您在文章最后一部分的想法——在同一个 API 中写入 SQL 和更新缓存——似乎是合理的。我会稍微改变一下:让缓存有一些低但合理的 TTL,比如 1 分钟。仅在命中数据库时更新读取缓存,以便在下一个数据库查询时命中缓存。

优点:

  1. 过了 1 分钟,您就知道您的用户正在获取正确的数据。
  2. 容错:如果缓存有问题并且由于某种原因您无法更新它,则下一个查询只是转到数据库,而客户端仍然会获取正确的数据。

缺点:

  1. 您将对 DB 进行更多的读取(尽管每分钟每个键额外读取 1 次应该没什么大不了的)。
  2. 客户端可以在更新后获取长达 1 分钟(最多 - 通常更少)的旧数据。
于 2015-09-30T23:04:19.453 回答
1

分片最重要的原则之一是尽量避免“跨分片”查询。如果不是这种情况,并且您还需要进行连接,我认为分片对您没有帮助。读取缓存都没有。我们在几个项目中大量使用分片。它确实对可扩展性有很大帮助,但正如我所说,我们的服务中只有很少一部分需要多个分片。之所以如此,是因为我们根据服务需求选择了分片键。我认为分片最重要的决定是选择正确的分片键。如果你能找到一个“完美”的分片键,你可以直接使用数据库而不需要任何缓存。至少这就是我们现在正在做的事情。

于 2015-10-01T21:03:28.787 回答