Java 带有我自己的时间戳的并发 ReadWriteLock
Java Concurrency ReadWriteLock with my own timestamp
ReentrantReadWriteLock
非常适合在接收时以编程方式基于时间戳的读写场景。
PUT(KEY=1,VALUE=1)
PUT(KEY=1,VALUE=2)
GET(KEY=1)
PUT(KEY=1,VALUE=1)
...
Java ReentrantReadWriteLock
将根据 Java 本身提供的时间戳按顺序自动同步所有这些。
但是,我需要如何使用随每个请求一起提供的外部时间戳。
PUT(KEY=1,VALUE=1,TIMESTAMP=13000000000000)
PUT(KEY=1,VALUE=2,TIMESTAMP=13500000000000)
GET(KEY=1,TIMESTAMP=14000000000000)
PUT(KEY=1,VALUE=1,TIMESTAMP=15000000000000)
...
如何设计按外部时间戳排序的ReadWriteLock?
简答:
同步接收时间戳数据的通道,或在接收端使用有序的并发数据结构,如 ConcurrentSkipListMap
。同时质疑你是否需要维持这个顺序。
P.S。 ReentrantReadWriteLock
不使用时间戳等可比较的实体来建立排序,其公平调度算法不包括您可以重复使用的条目的重新排序。 ReentrantReadWriteLock
通过 AbstractQueuedSynchronizer
.
使用基于 CLH 的锁队列
长答案:
虽然您想做的事情很可能是您无法避免的事情,但质疑您是否真的需要并发 and/or 分布式系统中的各种精度和一致性总是好的。
你为什么关心这个问题?
听起来您想通过使用系统中另一层的数据排序来保持公平。您是否需要将这两层分开,可能是因为其中一层不受您的控制,或者因为它们需要在语义上保持分离?如果是这样,您可以在这里再问自己几个问题。
是否绝对有必要为每个请求维护此顺序?
这种订购是您业务逻辑的重要组成部分吗?
它实际上是由您关心的上层组件建立的吗?
- 如果它是基于某些请求通过您无法控制的网络(如 Internet)到达的时间,您可能并不真正关心这种排序,放松一致性要求可能会导致在更高的吞吐量。在高度并发、不公平的环境中,与在资源利用有问题的公平环境中的请求相比,服务速度更快的情况并不少见。
- 如果它基于对所有请求建立总顺序的单个超快时间戳发布者,您可以修改您的系统,以便时间戳发布者成为服务于通过 Disruptor 或 ArrayBlockingQueue 向系统的第二层请求。
您真的会收到乱序请求吗?
您可能正在解决一个您永远不会真正面对的问题,或者您将在遥远的未来某个地方遇到的问题,与此同时,您的时间可以更好地花在其他地方。
如果情况并非如此,并且您实际上希望收到无序的(在您的外部时间戳顺序中)请求,那么您的层之间的通信通道是在您的系统中引入 "disorder" 的组件之一.这可能是因为有人故意想用一致性来换取吞吐量,也可能是因为该通道在没有额外工作的情况下无法满足您系统的需求。
考虑是更容易在其中强制执行严格的一致性,还是更容易保持原样并在收到请求后对其进行排序。
- 我们已经通过为 SingleProducerTimestampIssuer™ 说明的方法触及了前者 - 如果您无法控制通道,它也可能不可行。
- 对于后者,可以尝试使用有序的并发数据结构。
ConcurrentSkipListMap
将时间戳映射到请求可能是一个很好的解决方案。如果您不害怕尝试应用论文中的想法,您可能想看看 Concurrent Programming Without Locks 和 Fast Concurrent Data-Structures Through
显式时间戳
ReentrantReadWriteLock
非常适合在接收时以编程方式基于时间戳的读写场景。
PUT(KEY=1,VALUE=1)
PUT(KEY=1,VALUE=2)
GET(KEY=1)
PUT(KEY=1,VALUE=1)
...
Java ReentrantReadWriteLock
将根据 Java 本身提供的时间戳按顺序自动同步所有这些。
但是,我需要如何使用随每个请求一起提供的外部时间戳。
PUT(KEY=1,VALUE=1,TIMESTAMP=13000000000000)
PUT(KEY=1,VALUE=2,TIMESTAMP=13500000000000)
GET(KEY=1,TIMESTAMP=14000000000000)
PUT(KEY=1,VALUE=1,TIMESTAMP=15000000000000)
...
如何设计按外部时间戳排序的ReadWriteLock?
简答:
同步接收时间戳数据的通道,或在接收端使用有序的并发数据结构,如 ConcurrentSkipListMap
。同时质疑你是否需要维持这个顺序。
P.S。 ReentrantReadWriteLock
不使用时间戳等可比较的实体来建立排序,其公平调度算法不包括您可以重复使用的条目的重新排序。 ReentrantReadWriteLock
通过 AbstractQueuedSynchronizer
.
长答案:
虽然您想做的事情很可能是您无法避免的事情,但质疑您是否真的需要并发 and/or 分布式系统中的各种精度和一致性总是好的。
你为什么关心这个问题?
听起来您想通过使用系统中另一层的数据排序来保持公平。您是否需要将这两层分开,可能是因为其中一层不受您的控制,或者因为它们需要在语义上保持分离?如果是这样,您可以在这里再问自己几个问题。
是否绝对有必要为每个请求维护此顺序?
这种订购是您业务逻辑的重要组成部分吗? 它实际上是由您关心的上层组件建立的吗?
- 如果它是基于某些请求通过您无法控制的网络(如 Internet)到达的时间,您可能并不真正关心这种排序,放松一致性要求可能会导致在更高的吞吐量。在高度并发、不公平的环境中,与在资源利用有问题的公平环境中的请求相比,服务速度更快的情况并不少见。
- 如果它基于对所有请求建立总顺序的单个超快时间戳发布者,您可以修改您的系统,以便时间戳发布者成为服务于通过 Disruptor 或 ArrayBlockingQueue 向系统的第二层请求。
您真的会收到乱序请求吗?
您可能正在解决一个您永远不会真正面对的问题,或者您将在遥远的未来某个地方遇到的问题,与此同时,您的时间可以更好地花在其他地方。
如果情况并非如此,并且您实际上希望收到无序的(在您的外部时间戳顺序中)请求,那么您的层之间的通信通道是在您的系统中引入 "disorder" 的组件之一.这可能是因为有人故意想用一致性来换取吞吐量,也可能是因为该通道在没有额外工作的情况下无法满足您系统的需求。
考虑是更容易在其中强制执行严格的一致性,还是更容易保持原样并在收到请求后对其进行排序。
- 我们已经通过为 SingleProducerTimestampIssuer™ 说明的方法触及了前者 - 如果您无法控制通道,它也可能不可行。
- 对于后者,可以尝试使用有序的并发数据结构。
ConcurrentSkipListMap
将时间戳映射到请求可能是一个很好的解决方案。如果您不害怕尝试应用论文中的想法,您可能想看看 Concurrent Programming Without Locks 和 Fast Concurrent Data-Structures Through 显式时间戳