【发布时间】:2012-05-09 05:39:02
【问题描述】:
我正在构建一个涉及大量图像处理的应用程序。我们在分布式庄园中构建它,任意数量的渲染机器从 RabbitMQ 交换接收渲染图像的请求。
因为在渲染过程中可能会出现对图像的请求,并且因为我不想让两个渲染服务器重复工作,所以我在 mySQL 图像表中创建了一个名为 is_rendering 的列作为布尔值。
当渲染服务器收到渲染请求时,它会执行一系列如下所示的步骤:
- 选择更新图像行
- 如果 is_rendering == true 中止渲染请求
- 设置 is_rendering == true 并提交事务
- 渲染图像并将缩略图存储在全球可访问的存储中
- 设置 is_rendering == false 并返回
它确实有效,但我担心这些频繁的数据库更新看起来有点傻。此外,我正在考虑渲染服务器在渲染过程中失败并留下 is_rendering == true 的边缘情况,从而阻止该图像被渲染。我正在考虑解决此问题的解决方案是将 is_rendering 列从 tinyint(1) 更改为 datetime 字段,并将锁定日期存储为“true”值,并将 null 存储为“false”值。定期服务健康检查可以选择所有具有 is_rendering 值的行超过某个时间段并在这种情况下释放锁定。
这是解决这个问题的明智方法,还是我应该考虑其他更优雅的方法?
【问题讨论】:
-
我已经成功实现了几次日期时间字段锁定方法
-
我没有看到任何其他的锁定方式,除了引入这样一个列。只有我会把它变成一种状态,比如
0 = not_rendered, 1 = rendering, 2 = rendered。但也许我有点误解了你的工作流程。当然,使用InnoDB事务将确保只有一个并发查询可以将图像设置为呈现状态。 -
我不知道这种方法本身是否合理,但作为列的替代品,单独的 1:1
is_rendering (int)表对我来说似乎更易于管理。只需添加/删除记录,您就不必扫描健康检查中的所有图像记录。但是,如果您同时需要图像本身,则可能需要额外的工作。 -
@Quail 好吧,就性能而言,拥有单独的
(id, is_rendering)索引与拥有单独的表相同。 -
@Shedal - 所以这种方法仍然不能解决服务器在渲染过程中死机并锁定图像的边缘情况。如果服务器死了,没有明确的方法可以让锁过期,除非在其中嵌入日期并拥有一个辅助服务来查看所有当前持有的锁并清除在合理的渲染时间之后持有的锁。
标签: mysql distributed-transactions