高频计费系统的MySQL设计

标签 mysql multithreading billing

我觉得我会因为问这个问题而被屠杀,但事情就是这样......

我的每日订阅量为 500 万,预计/希望在 12 个月内达到 5000 万。我需要非常非常快地续订/开具账单。我已经尝试了我能想到的索引和循环的所有排列,但它的 SELECT 查询仍然太慢。也许我的错误是 MySQL 设计,也许是我使用 MySQL 的守护进程,也许只是因为我正在使用 MySQL - 请让我知道您的想法和/或建议。谢谢!

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

  • subscription_id (PK)
  • subscriber_id
  • 服务编号
  • 添加日期
  • 当前开始日期
  • 当前结束日期
  • bill_date(用于确保两个线程不会同时抢帐)
  • last_successful_bill_date
  • 有_outstanding_balance

** Money-people-owe-me 表看起来像这样*

  • 编号
  • subscription_id(英国)
  • 未结余额
  • 下一个账单日期
  • number_bill_attempts
  • (相当多的人并不总是付费,我在继续尝试计费的同时给他们提供了一段时间的无偿访问权限,但最终我还是切断了他们的服务)

** Billing Daemon 看起来像这样 **

  • 在多台机器上运行多线程:
  • 对于每项服务
    • stuffToBill[] = SELECT stuff ORDER BY next_bill_date FOR UPDATE LIMIT XXX;
    • UPDATE stuff SET next_bill_date = later WHERE id IN (stuffToBill[ids])
    • 提交
    • 将他们放入计费人员的队列中

运行 EXPLAIN 显示我正在使用合适的索引,但是 SQL 的细节加上我在多个服务器上运行相同的守护程序的事实使得它锁定/通常使我的 DBM 上的 I/O 队列过载。 DBM 是优质硬件。

再次感谢您的建议!

最佳答案

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

     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 使用等事项的预设参数通常不适合像您这样的生产系统。

关于高频计费系统的MySQL设计,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19126895/

相关文章:

mysql - magento mysql 主/从复制 - 未使用从属

php - Mysql 表更新操作无明显原因失败

java - 基本类型是易变的还是同步的?

android - 更新后应用内计费不起作用 - Google 商店

android - Google Play 控制台中的 "Resubscribe not available"警告消息

java - Mysql 正在保存从 Java 应用程序输入提供的 1 天前的日期

php - 使用 php/mysql 进行简单的 php 分页或 css 分页

c - C 中带有进程和 2 个线程的信号处理不起作用

c++ - 为什么taskset对fedora没有影响?

android - 测试购买未显示在 Google 电子钱包商家中