高频计费系统的MySQL设计

时间:2013-10-01 22:13:46

标签: mysql multithreading billing

我有一种感觉,我会因为提出这个问题而被诅咒,但在这里它会......

我每天有500万订阅量&期望/希望在12个月内拥有5000万。我需要非常快速地续订/收费。我已经尝试了索引和放大器的每个排列。循环我能想到,但它的SELECT查询仍然太慢。也许我的错误是MySQL设计,也许是我使用MySQL的守护进程,也许只是因为我使用MySQL - 请让我知道你的想法和/或建议。谢谢!

**订阅表看起来像这样**

  • subscription_id(PK)
  • subscriber_id
  • 的service_id
  • add_date
  • current_start_date
  • current_end_date
  • bill_date(用于确保两个线程不会同时收费)
  • last_successful_bill_date
  • has_outstanding_balance

** Money-people-owe-me表格看起来像 *

  • id
  • subscription_id(英国)
  • outstanding_balance
  • next_bill_date
  • number_bill_attempts
  • (相当多的人不总是付钱,我给他们一点点无偿访问,而我继续尝试收费,最后我切断了他们的服务)

** Billing Daemon看起来像**

  • 在多台计算机上运行多线程:
  • 对于每项服务
    • stuffToBill [] = SELECT stuff ORDER BY next_bill_date FOR UPDATE LIMIT XXX;
    • UPDATE stuff SET next_bill_date =稍后WHERE id IN(stuffToBill [ids])
    • COMMIT
    • 将它们放在计费工作人员的队列中

运行EXPLAIN表明我使用了不错的索引,但SQL的细节以及我在多个服务器上运行相同守护程序这一事实使得它锁定/通常会使我的DBM上的I / O队列过载。 DBM是高质量的硬件。

再次感谢您的建议!

1 个答案:

答案 0 :(得分:1)

您似乎正在使用选择/更新/提交机制来确定要计费的帐户,如下所示:

     SELECT stuff 
   ORDER BY next_bill_date 
 FOR UPDATE 
     LIMIT XXX;

    UPDATE stuff 
       SET next_bill_date = later
     WHERE id IN (stuffToBill[ids]);

    COMMIT;

您的SELECT语句可以通过添加一个可行的WHERE子句来改进,该子句只选择到期的账单或其他一些标准。为了找到最老的账单,查看所有账单是没有意义的。像

这样的东西
  WHERE next_bill_date <= TODAY() + INTERVAL 30 DAYS

可能会成功。如果你做得对,那么SELECT查询的复杂性将会降低。如果正确索引next_bill_date,则可以使用索引。

您也可以尝试使用LIMIT BY xxxx值的大小。你可能在这里使用了太大的值,而且你的更新速度令人不快。

最后,你需要考虑做一些严肃的MySQL和InnoDB调优。控制RAM使用等预设参数通常不适合像你这样的生产系统。