如何在高流量应用程序中将写查询从MySQL迁移到Redis



几年来,我一直在开发一个高流量广告服务平台,使用一个主控Maria DB集群,前面有一个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中的信用额度是微不足道的,但一旦用户开始每秒发送多次点击,问题就会开始出现(主要是集群中的死锁或达到最大连接数(。

在Redis中应用信用减免是最好的,但我很难将Redis中的一堆信用记录之间的点连接起来,也很难在此基础上过滤和排序MySQL记录。

对于这个问题,有什么好的方法可以让我尽可能少地接触MySQL?或者,为了实现这一点,我需要采取一种完全不同的方法。

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

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

Redis是一个内存数据库,它不像MySQL那样有ACID事务保证。因此,即使您启用了AOF,在写入Redis后,您的数据仍有一些丢失的机会,这可能会使您的数据不一致。

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

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

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

最新更新