求教关于Ehcache的死锁问题处理

最近有个项目要使用cache,正在做Ehcache的技术试验。
现在同事向我提出一问题:
Ehcache内部如何管理缓存更新?
业务场景:可能存在多个线程同时向一个cache更新数据(总量约为平均每秒3万条左右),IBM MQ我们做过试验,在代入业务逻辑的场景下,这个吞吐量可能吃不消。现在准备自己实现业务逻辑,用cache缓存数据提供给前端的Server使用。如果 2个线程同时更新缓存中的同一条记录(比如线程1处理了第一秒的数据,线程2处理了第2秒的数据,但是线程1由于其他原因导致与线程2同时向cache put element)
请问这种情况下内部更新机制如何?
PDF读了一遍,貌似没有看到关于这方面的描述,只有FIFO,LRU,LFU的介绍。

两个线程如果同时修改一个Cache中不同的两个数据,他们之间不会互相影响。也不会造成死锁。

如果修改的数据是同一个,则后写的线程的数据将被保留。也没有死锁的问题。

Ehcache枷锁的基本原理如下:
Ehcache是在读的时候对Key获取一个读锁,这样并发读互相不会影响。当写的时候,对Key获取一个写锁,同一时刻只能有一个线程获得写锁,因此会屏蔽掉其它的写线程和读线程。等写操作完成后,写锁倍释放,其它线程可以进来继续其它操作。

如果还有疑问,请把问题进一步描述清楚。

谢谢!

老马

感谢老马。
补充一个问题,就是如果采用了集群缓存的环境,两个节点上的不同线程分别对各自节点缓存中的同一个数据进行写操作,那么此时的写锁生效么?如何同步呢?

如果两个节点分别在各自节点修改同一个共享的数据(PUT),写锁会生效的。最后一个PUT的节点的数据会被保存在共享缓存中。

不过如果你先从CACHE中GET出一个数据,然会分别修改这个对象,这种情况下,由于对象已经脱离CACHE,也就没有任何保护。对这个对象的修改是没有锁的。只有在PUT的时候锁才会生效。

如果你那到的是个银行帐户信息。
两个节点分别往里面存100元钱。Ehcache的写锁不能保证最后的结果是帐户增加了200元。如果要达到这个效果,必须使用ExplicitLockingCache来实现对Key的锁,而不只是在PUT或者GET的进行枷锁。

老马

老马,你的意思是如果我在节点一进行了PUT操作,对一个缓存对象进行了update,那么在我put的过程中,实际上集群内的节点二、节点三等等此时该对象的一个本地副本都是处于写入锁状态的么?

是的。在PUT的过程中,数据事有保护,并且安全的。

老马

两个线程如果同时修改一个Cache中不同的两个数据,他们之间不会互相影响。也不会造成死锁。

如果修改的数据是同一个,则后写的线程的数据将被保留。也没有死锁的问题。

Ehcache枷锁的基本原理如下:
Ehcache是在读的时候对Key获取一个读锁,这样并发读互相不会影响。当写的时候,对Key获取一个写锁,同一时刻只能有一个线程获得写锁,因此会屏蔽掉其它的写线程和读线程。等写操作完成后,写锁倍释放,其它线程可以进来继续其它操作。

如果还有疑问,请把问题进一步描述清楚。

谢谢!

老马 

Ehcache的这种锁机制,对于业务来说是没有多大意义的.
业务中更多的是需要保证数据的一致性:
即对于缓存中的有一个数据,当线程1更新之后,线程2的更新需要基于线程1的更新来做,否则,线程2的更新将直接冲掉线程1的更新,导致业务出错.
如上述存钱的问题,最后导致客户不见了100块,这是业务绝对不可以接受的.

正确的锁机制应该是:
每个缓存数据都应该有一个版本号, 当线程1更新数据之后,要同步更新版本号, 线程2更新的时候应该检查手中数据版本号与缓存中的是否一致,
一致才可以更新, 如果不一致,就不允许更新,并给出警告.

猜你喜欢

转载自chxiaowu.iteye.com/blog/1178262
今日推荐