我正在学习缓存,并对缓存的并发性有疑问。
据我所知,LRU缓存是使用双链表+哈希表实现的。那么LRU缓存如何处理高频并发?请注意,从缓存中获取数据并将数据放入缓存都会更新链接列表和哈希表,因此缓存会一直被修改。
如果我们使用互斥锁进行线程安全,如果大量人员访问缓存,速度是否会降低?如果我们不使用锁,会使用什么技术?提前谢谢。
答案 0 :(得分:10)
传统LRU高速缓存不是为高并发性而设计的,因为硬件有限并且命中代价远小于未命中代价(例如数据库查找)。对于大多数应用程序,如果缓存仅用于更新底层结构(不计算未命中的值),则可以接受锁定缓存。当锁争用时,分割LRU策略等简单技术通常就足够了。
制定LRU缓存规模的方法是避免在每次访问时更新策略。要做的重要观察是缓存的用户不关心当前LRU的排序。调用者唯一关心的是缓存保持阈值大小和高命中率。通过避免在每次读取时改变LRU策略,这为优化打开了大门。
memcached采用的方法是丢弃时间窗内的后续读取,例如1秒。预计缓存将非常大,因此通过这个更简单的LRU驱逐一个可怜的候选人的可能性非常小。
ConcurrentLinkedHashMap(CLHM)以及随后Guava's Cache采用的方法是将访问记录在缓冲区中。此缓冲区在LRU的锁定下耗尽,并且使用try-lock
不得阻止其他操作。 CLHM使用多个环缓冲区,如果缓存无法跟上,则会有损耗,因为丢失事件优于降低性能。
Ehcache和redis采用的方法是概率LRU策略。读取更新条目的时间戳,写入迭代缓存以获取随机样本。最旧的条目将从该样本中逐出。如果样本构建速度快且缓存很大,那么被驱逐的条目可能是一个很好的候选者。
可能还有其他技术,当然还有伪LRU策略(如CLOCK),可以在较低的命中率下提供更好的并发性。