我目前正在设计一个具有以下结构的服务器:
ConcurrentHashMap的地方执行一些工作,并分析结果。工作完成后,结果将被发布到写队列中。ConcurrentHashMap的写请求ConcurrentHashMap。服务器约束:
ConcurrentHashMap中的特定条目,写入将在读取发送到网络之前几秒钟发布到网络。线程绝不能允许在写入之前对读进行调度。到目前为止,我的想法:
是否有任何方法可以确保在写之前阅读的可能性很低,或者我已经采取了足够的预防措施?我应该使用读重试机制吗?
另外,是否实际需要写队列,或者我是否可以更一般地使用工作线程来处理写入?写订单并不重要。
发布于 2019-07-12 12:34:00
别浪费时间。在分布式系统中,它们很容易处理,并且容易出错,特别是因为您需要同步时钟和处理延迟。相反,使用版本号。对于每个写入请求,增加数据上的版本号;对于每个读取请求,发送一个版本号以有条件地执行请求,如果读取请求的版本号与资源的当前版本不匹配(或者,如果您的应用程序可以容忍从未来版本读取,则放松匹配条件,使其不匹配),然后拒绝读取请求(请求客户端可以等待几秒钟并重新发送读取请求),或者将其放回读队列并等待适当的写入请求到达。
为了获得额外的可靠性,读取队列可以是一个优先级队列。版本号是优先级,如果优先级队列的前端(版本号最低的项)高于资源的当前版本,那么读线程应该阻塞,直到写线程由于写事件而唤醒它,或者被一个队列唤醒到比队列中的任何其他条目都有较低版本号的读队列(即,它被插入到优先级队列的前面)。
发布于 2019-07-11 21:16:39
我不完全理解您的应用程序做了什么,但您的关注和方法似乎是不存在的。
发布于 2019-07-12 12:05:08
首先,我希望3-5秒左右的时间是一个足够大的开端,可以在阅读之前完成。
假设这样的事情真的是个坏主意。您应该编写代码来处理这样一个事实,即读取可能首先出现。
因此,如果数据陈旧,您希望read操作等到更新后再执行,对吗?您可能需要使用条件对象。如果数据陈旧,则创建/重置一个条件对象,在更新数据时,写入操作将发出该条件对象的信号。
让线程进入睡眠状态是可行的,但也有一些权衡。例如,它睡多长时间?如果您的睡眠太短,线程只会占用CPU时间,什么也不做。如果您的睡眠时间过长,则应用程序的响应性较差。
使用锁、信号量或条件对象编写代码更简单,响应更快(读取操作只会阻塞,直到有有用的事情可做)。
另外,请参阅实践中的Java并发一书。并发是很难得到正确的,这本书讨论了许多意想不到的问题,以及如何正确地做所有这些事情,包括如何测试它!
https://softwareengineering.stackexchange.com/questions/394569
复制相似问题