mysql - 如何在 MySQL 上创建事件流

标签 mysql stream innodb

给定以下 InnoDB 表:

event_stream
+ id BIGINT PRIMARY AUTO-INCREMENT
+ event TEXT

考虑到有多个客户端同时向这个流中插入事件:我们可以使用什么技术来让多个监听器/消费者以增量方式处理这个事件流?

(编辑)我希望有多个客户端 连接到这个流,它们可以对新事件做出一次 react 并跟踪它们在流中的位置。

注意事项:

  • 不使用 MySQL 来存储事件不是一种选择;
  • 锁定整个表是 Not Acceptable ;
  • 我想控制一个事件是否已经由消费者决定,这个表可能有多个消费者;
  • 可以创建新列;
  • 此表将增长到数亿个事件;

最佳答案

“不要排队,直接去做。”我发现数据库的排队机制很差。如果“工作”线程执行任务的时间不长,则让队列简单地执行任务;这消除了队列的开销,从而可能使系统更快并更好地扩展。

“数以亿计的事件”——而且几乎所有事件都已“处理”?这表明您有两个表——一个用于已处理的事件,一个用于等待处理的事件。后者很少有超过几十行??在这种情况下,处理效果会更好。

有两个额外的列:哪个 worker 拥有该进程,以及 worker 何时捕获它。时间到了,您可以处理这样的情况(是的,最终会发生)一个 worker 捕获了一个任务,然后死了——从而使任务成为孤立的。作为单独的工作可以“收割”这些孤儿。

单个 SQL UPDATE 可以获取表中的一行。单独在事务中执行此操作,在流程中的任何事务中执行此操作。同样,在其自己的事务中“释放”任务。

抓取是这样的(autocommit=ON):

UPDATE ToDo SET who = $me, when = NOW()
    WHERE who IS NULL
    LIMIT 1;   -- grab one
SELECT ... FROM ToDo WHERE who = $me;  -- get details on the task

“发布”可能涉及两个表,如下所示:

BEGIN;
$stuff = SELECT ... FROM ToDo WHERE who = $me;
DELETE FROM ToDo WHERE who = $me;
INSERT ... INTO History ... VALUES (most of stuff from $stuff);
COMMIT;

在抓取和释放之间,您有足够长的时间来执行“任务”。您不会被 InnoDB 超时等问题绊倒。

如果您想提供有关您的队列和任务的更多详细信息,我可能会进一步完善。

我所描述的内容应该可以处理任意数量的插入器、任意数量的工作人员和持续任意时间长度的任务。

AUTO_INCREMENT 对于遍历事件列表可靠。 INSERT 是多个步骤:

  1. 开始交易
  2. 获取下一个 auto_incr id
  3. 插入
  4. COMMIT -- 只有现在其他人才能看到新的 id

COMMIT 相对于 auto_incr 可能“乱序”(尤其是在复制中)。

关于mysql - 如何在 MySQL 上创建事件流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47465040/

相关文章:

php - 修复简单的 PHP WordPress 用户显示名称脚本

C++文件流打开模式歧义

php - 选择更新和 php 脚本

mysql - 从 MyISAM 迁移到 Innodb 时代码发生变化

php - MySql 计算表列中的重复项

mysql - 从不同的表中计算产品和价格总和

c++ - 更改 cin (c++) 的分隔符

mysql - 是什么导致 RDS 上的 MySQL 每 5 分钟出现一次 CPU 峰值?

mysql - 列出继承? SQL 和类

javascript - 如何从node.js获取音频流?