- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个难题,也许你能帮帮我。
我有一个用作工作队列的表。记录已插入,需要处理。处理完一条记录后,它会从队列中删除。有一些限制:
假设 entity1 和 entity2 都想从表中选择一个处理切片。如果 entity1 选择 row1,则 entity2 可以选择除 batch1 之外的任何其他内容(除 row1 和 row2 之外的任何其他内容)。
让我们抽象出处理部分,因为实际处理是什么并不重要。我很想知道如何仅使用 mysql 数据库来阻止实体相互冲突,同时保持处理的并行性。
从我的角度来看,我看到两个非常笼统的方向:
我很想知道:
所以我这里的是,数据库必须在不同的实体之间拆分一个表,以便进行处理,并且想知道最好的方法来做到这一点。我几乎不认为我是第一个处理这个问题的人,并且想知道你的想法。另外,请注意,可以通过相当简单的标准(例如,batchId)将记录分批分割
亲切的问候,
安德烈。
最佳答案
嗯,根据您的描述,我看不出数据库记录锁定如何满足您的要求。数据库锁说“如果这条记录不可用,请稍等”,而不是“如果这条记录不可用,请选择另一条”。
问题:当一个批处理被处理时,它就“完成”了吗?我的意思是,假设节点 A 开始处理批处理 1。然后节点 B 出现,不管你怎么做,发现批处理 1 正在工作,所以它从批处理 2 开始。然后节点 A 完成。然后节点 C 出现了。当前未处理第 1 批。节点 C 应该获得批处理 1 吗?或者第 1 批已经完成,第 2 批正在工作,所以我们必须继续第 3 批?如果批处理完成,那么任何数据库锁定显然都不会起作用,因为它不记得过去访问过记录,只记得现在发生的事情。
也许其他人有更聪明的解决方案,但我认为您将不得不使用状态标志来做到这一点。我会说:
创建一个单独的 Batch 表,每个批处理有一条记录。在指向 Batch 表的 Work-queue 表中放置一个外键。这样我们就可以保持数据标准化。
在批处理表中,添加一个状态标志,其中包含工作中和非工作的值;或未处理、在制品和已处理。 (取决于批处理是否一劳永逸地“完成”。)还创建一个“处理实体”字段,如果它正在工作,则标识正在处理该批处理的实体,否则为空。 (如果状态只有 in-work 和 not-in-work,则此字段可以兼作 in-work 标志:null=not in-work,not null=in-work。)
当实体开始处理批处理时,它会将处理实体字段设置为实体 ID。完成后,它将字段重置为空。当一个实体正在寻找要处理的批处理时,它会选择“where processing_entity is null”(当然还有任何其他条件)。
然后为了确保实体没有崩溃而留下标志设置,每次实体启动时,它都会检查是否有批处理记录表明它正在处理它。如果是这样,它一定是崩溃了,所以它会重置标志并进行任何清理工作。
这只有在实体集是固定的情况下才有效,例如如果实体是服务器,或者它是来自线程池的线程。如果它们是可以任意来来去去的线程,那将无法正常工作,因为您不能指望线程重新启动来表明它还有未完成的工作。
我使用的另一种方法是在批处理记录中放置一个时间戳,说明我们何时开始处理。然后我有另一个不时运行的进程,检查时间戳,并与一些合理的最大时间进行比较。比方说,如果我们知道该进程应该花费几秒钟,而我们看到一个时间戳为一小时前的进程,那么该进程要么终止要么挂起,我们应该适本地进行清理。这确实有一个问题,即它要求您能够说出最长时间是多少。
关于MySQL : splitting the processing of a particular table between different nodes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10488902/
我是一名优秀的程序员,十分优秀!