【问题标题】:Is using a mySQL column a sane way to achieve global locking?使用 mySQL 列是实现全局锁定的明智方法吗?
【发布时间】:2012-05-09 05:39:02
【问题描述】:

我正在构建一个涉及大量图像处理的应用程序。我们在分布式庄园中构建它,任意数量的渲染机器从 RabbitMQ 交换接收渲染图像的请求。

因为在渲染过程中可能会出现对图像的请求,并且因为我不想让两个渲染服务器重复工作,所以我在 mySQL 图像表中创建了一个名为 is_rendering 的列作为布尔值。

当渲染服务器收到渲染请求时,它会执行一系列如下所示的步骤:

  1. 选择更新图像行
  2. 如果 is_rendering == true 中止渲染请求
  3. 设置 is_rendering == true 并提交事务
  4. 渲染图像并将缩略图存储在全球可访问的存储中
  5. 设置 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


【解决方案1】:

亲爱的,据我了解,如果您遵循以下规则,您的第一种方法也是正确的: 1)你的表类型是innoDB。 2)您在代码中使用事务。因为如果在更新过程中发生任何中断,它将回滚。

最后,您的第二种方法也更好。如果你没有满足我提到的几点

【讨论】:

  • 我正在使用 InnoDB。我认为在整个渲染过程中保留事务是不明智的。渲染可能需要 30 多秒才能完成,我正在使用连接池。坚持交易意味着我必须绑定一个可以在其他地方使用的连接。
【解决方案2】:

我已经着手将实现更改为使用DATETIME 列。

我真的很好奇这是否是对 mySQL 的一般使用不当。根据我的研究,我可以使用 Hadoop 的 ZooKeeper:http://zookeeper.apache.org/doc/r3.1.2/recipes.html 或 Google 的内部 Chubby 系统。由于这只是服务的第一次迭代,我将坚持使用 mySQL。

从我在这里阅读的内容以及我在网上阅读的内容来看,使用 mySQL 作为生成全局锁的一种方式并不是一个糟糕的主意,将其更改为 DATETIME 列虽然有点迟钝,但实施过期策略以处理机器在处理作业过程中关闭的奇怪边缘情况的最佳方法。

持有事务级锁将是另一种方法,但当单个服务器运行具有小连接池的多个线程时它没有意义,它会不必要地占用连接,尽管它有一个内置的-当客户端连接丢失时过期。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 2010-12-10
    • 2015-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多