【问题标题】:How to Migrate Write Queries Away From MySQL to Redis In a High-Traffic Application?如何在高流量应用程序中将写入查询从 MySQL 迁移到 Redis?
【发布时间】:2020-12-17 15:12:02
【问题描述】:

我多年来一直在开发一个高流量的广告服务平台,使用一个主-主 Maria 数据库集群,前面有一个 HAProxy 来平衡关系数据查询(读取查询到所有服务器,但只写入为一,以防止服务器不同步)。我所说的关系数据是指活动设置、用户详细信息、付款等内容。我也在使用 Redis 来缓存一些不太动态的 MySQL 信息,但我相信有很多机会可以更好地利用它,因为一旦流量增加,我就会经常遇到瓶颈,例如:

  • 与 MySQL 的连接过多
  • 死锁(可能是因为当主服务器过载时,多台服务器开始写入)。

我的目标是将尽可能多的写入从 MySQL 转移到 Redis,但我很难根据存储在 Redis 中的计数/预算来过滤 MySQL 数据,尤其是在传统 JOIN 的地方用过。

这样的 MySQL 查询的简化示例会在用户预算内获得最高出价的广告系列:

SELECT campaigns.id, campaigns.url FROM campaigns
JOIN users ON campaigns.user_id = users.id
ORDER BY LEAST(users.credits, campaigns.bid) DESC
LIMIT 1;

在该广告系列获得点击后,需要立即削减预算。当然,减少 MySQL 中的 credits 是微不足道的,但是一旦用户开始每秒发送多次点击,问题就开始出现(主要是集群中的死锁或达到最大连接数)。

在 Redis 中应用信用减少是首选,但我在连接 Redis 中的一堆信用记录之间的点以及基于此过滤和排序 MySQL 记录时遇到了麻烦。

什么是解决这个问题的好方法,可以让我尽可能少地接触 MySQL?或者也许我需要采取完全不同的方法来实现这一点。

任何建议或链接将不胜感激。

【问题讨论】:

  • 避免写入连接问题的一种可能方法是写入 Redis 流(或 Kafka)之类的东西,然后使用消费者从主题中读取并执行批量插入 MySQL 写入器。然后你仍然可以使用 MySQL 进行读取。不同之处在于,从插入记录到消费者将信息放入 MySQL 之间会有延迟。您可以从一个表开始,然后根据需要添加更多表以减少连接超时。
  • 这是我从未想过的,但听起来很有希望。这样的策略我应该期待什么样的延迟?我有一种感觉,这可以以近乎实时的方式实现。我是不是太乐观了?
  • @user1782560 这将是接近实时的,延迟将主要在消费者端,因此您可以期望消费者应该能够在 1-2 秒内写入,这也取决于 Kafka或 Redis 流延迟。像 Redis Stream 这样的系统会为您提供 Ms 延迟,但 DB 写入可能需要一些时间。明智的做法是等待 N 条记录而不是写入一条记录,如果没有足够的记录怎么办,因此您应该结合使用计时器和批量大小。

标签: mysql redis


【解决方案1】:

我不建议将所有写入请求都移至 Redis,尤其是对于具有强一致性的数据(如支付)。

Redis 是内存数据库,不像 MySQL 那样有 ACID 事务保证。所以即使你开启了 AOF,你的数据在写入 Redis 后仍有一些机会丢失,这会导致你的数据不一致。

对于您的情况,您可以集成消息队列(Kafka、rabbitMQ)以避免连接问题和死锁:

  1. 当事务发生时,将请求序列化并写入数据并发送到消息队列。
  2. MySQL 会以固定的消耗率(根据您的需要)监听 MQ,并将数据顺序写入 MySQL(如果需要缓存,则重写到 Redis)
  3. 对于客户端,您可以让线程在无限循环中查询结果,直到写入完成。这将使异步写入像同步一样执行。

在这种情况下,您将避免资源竞争(如死锁),并且还将通过固定消耗率平滑写入速率。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-04
    • 1970-01-01
    • 2010-09-30
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    相关资源
    最近更新 更多