2017-08-07 122 views
1

快速背景:当我回去重新设计应用程序的某些关键部分时,我一直在考虑锁定及其对性能的影响。该应用程序有一个大型的Tree风格的数据结构,可以缓存数据库中的数据/ DTO。对大树的更新可以通过两种主要方式实现:1.用户触发的命令,2.自动更新来自在后台运行的作业。锁定性能:锁定更长时间与锁定更经常

当任何操作类型发生(用户/自动)时,我锁定(显式锁定)数据结构。我遇到了一致性问题,因此锁定一切似乎最能保护缓存中数据的完整性。

问:由于许多自动更新可以发生在一次我想实现某种队列(JMS或许)来处理的数据结构,其中的任何用户驱动的更新推送到顶部和处理的第一个指令。当谈到处理批量/未知大小的自动“任务”集时,我试图弄清楚我是否应该让它们单独运行和锁定,或者尝试按时间将它们集中在一起,并与锁定进行一次交互。问题的真正症结在于任何更新的任务都可能影响整个树。

就整体性能而言(通常,没有特定的),是否有更多的事务锁定潜在的大型更新,或尝试并结合到一个大规模批量更新,只锁定一次,但更长的时间?我知道很多这可能取决于数据,更新类型,频率等。我不知道是否存在“更小更频繁的锁”或“更大的可能更长的锁”的一般经验法则。

+0

是的。嗯。也许没有。也许也许吧。好,严重:我认为你的问题太广泛了。 – GhostCat

+0

@GhostCat我有一个暗示它可能有点太宽泛。你能想出一些我可能缩小一点的方法吗?如果它是def,我就没有问题了。太宽泛。 – Walls

+0

什么是缓存策略?物体是否比所需要的时间更长,增加了树的大小并影响了性能? –

回答

1

我认为答案取决于您的程序是否在解锁数据结构上花费了大量时间。如果没有,我建议为所有未决更新锁定一次。

原因是,当更新线程再次快速锁定资源时,可能正在等待锁定的其他线程可能会被唤醒,然后无用地发送回睡眠状态。或者更新被另一个可能不利于缓存利用率的线程中断。此外,与更新相比,锁定成本可能很小:管道可能需要刷新,内存访问可能不会自由重新排序等。

如果线程在更新之间花费了一些时间而无需锁定数据结构,如果预计其他线程可以完成它们之间的事务并因此减少争用,我会考虑重新锁定每个更新。

请注意,当针对不同的更新有不同的优先级时,例如我认为用户更新与后台更新不同时,如果可以在较低优先级的更新中锁定数据结构很长时间任何方式阻止运行更高优先级的任务。

1

如果你最终实现某种类型的队列,那么你将失去所有的并发性。如果您一次收到1000个请求,请考虑一下效率如何。

试着看看这段并发树的代码。 https://github.com/npgall/concurrent-trees

+0

允许更少的并发活动连接将在大多数情况下提高整体性能。当然,它总是取决于。 https://stackoverflow.com/questions/1208077/optimal-number-of-connections-in-connection-pool – daniu

+0

问题是数据本身将会在除缓存树之外的全局事务中触及数据库。一个简单的并发数据结构不会增加事务性的好处。 – Walls