python - ZeroMQ 对于数据库事务来说太快了

标签 python postgresql sqlalchemy zeromq

在 Web 应用程序 (Pyramid) 中,我在 POST 上创建了某些对象,这些对象需要对其进行一些处理(主要是从 Web 上获取一些东西)。这些对象在 SQLAlchemy 的帮助下保存到 PostgreSQL 数据库中。由于这些任务可能需要一段时间,所以它不是在请求处理程序内部完成的,而是卸载到不同主机上的守护进程。创建对象时,我获取它的 ID (这是客户端生成的 UUID )并通过ZeroMQ 到守护进程。守护进程接收ID,并从数据库中获取对象,运行并将结果写入数据库。


问题:
守护进程可以在创建事务提交之前收到ID。由于我们使用的是 pyramid_tm,所以当请求处理程序无错误返回时,所有数据库事务都会被提交,我宁愿保持这种状态。在我的开发系统上,所有东西都在同一个盒子上运行,所以 ZeroMQ 快如闪电。在生产系统上,这很可能不是问题,因为 Web 应用程序和守护进程在不同的主机上运行,​​但我不想指望这一点。

这个问题最近才出现,因为我们之前使用的 MongoDB 的 write_convern 为 2。只有两个数据库服务器,实体上的 write 总是阻止网络请求直到实体被持久化(这显然不是最好的主意)。

  • 有没有人遇到过类似的问题?
  • 您是如何解决的?

我看到了多种可能的解决方案,但其中大部分都不令我满意:

  • 在触发 ZMQ 消息之前手动刷新事务。但是,我目前使用 SQLAlchemy after_created 事件来触发它,这非常好,因为它完全分离了这个过程,从而消除了“忘记”告诉守护进程工作的风险。还认为我仍然需要在守护进程端使用 READ UNCOMMITTED 隔离级别,对吗?
  • 向 ZMQ 消息添加时间戳,使接收消息的工作线程在处理对象之前等待。这显然限制了吞吐量。
  • Dish ZMQ 完全简单地轮询数据库。不!

最佳答案

我只会使用 PostgreSQL 的 LISTEN and NOTIFY功能。 worker 可以连接到 SQL 服务器(它已经必须这样做),并发出适当的 LISTEN。然后 PostgreSQL 会在相关事务完成时通知它。您在 SQL 服务器中触发生成通知甚至可能会在有效负载中发送整行,因此工作人员甚至不必请求任何东西:

CREATE OR REPLACE FUNCTION magic_notifier() RETURNS trigger AS $$
BEGIN
  PERFORM pg_notify('stuffdone', row_to_json(new)::text);
  RETURN new;
END;
$$ LANGUAGE plpgsql;

有了它,一旦知道有工作要做,它就会获得必要的信息,因此它可以开始工作而无需另一次往返。

关于python - ZeroMQ 对于数据库事务来说太快了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22245407/

相关文章:

python - python 中的基本正则表达式问题可帮助我学习它

python - 如何在python中执行shell命令文件

sql - 查询和选择SQLAlchemy中的特定列

python - 如何在各个字符串中分隔其间具有可变数量空格的长字符串

python - 绘制 kmeans 的输出(PyCluster impl)

database - pgsql2shp postgresql 错误

sql - 按值的数量对列进行排名

php - Postgres 中数组元素的自动涂层

python - SQLalchemy Core,检索更新行的 ID

python - Flask-WhooshAlchemy 与现有数据库