Dou*_*kem 7 java concurrency hibernate ehcache second-level-cache
我们有一个Java应用程序,它使用MySQL,Hibernate(3.5.1-Final)和EHcache(1.2.3)作为我们的二级缓存.
我们的hibernate.properties隔离级别是Read-committed isolation = 2
# 2-Read committed isolation
hibernate.connection.isolation=2
Run Code Online (Sandbox Code Playgroud)
在大量并发事务中,我们看到一个问题,即加载时某些集合(数据库关联)将抛出ObjectNotFoundException,并且看起来第二级缓存正在返回该集合的旧副本.
我们有许多不同类型的交易来访问这个集合(只读取),只有一些会添加/删除它的项目.
我们在单个事务负载或甚至中等事务负载(10 - 20个并发连接)下都没有看到此问题.
例如,我们有一个Character实体:
@Entity
@Table(name = "CHARACTERS")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Character extends AbstractCharacter implements Serializable {
...
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@OneToMany(mappedBy = "character", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private Set<CharacterItem> items;
Run Code Online (Sandbox Code Playgroud)
我们正在通过从包含它们的集合中删除实体并调用session.delete()来删除实体时正确维护对象图.
character.getItems().remove(characterItem);
session.delete(characterItem);
Run Code Online (Sandbox Code Playgroud)
我们尝试过更改Set项目; CacheConcurrencyStrategy来自:
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
private Set<CharacterItem> items;
Run Code Online (Sandbox Code Playgroud)
至
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
private Set<CharacterItem> items;
Run Code Online (Sandbox Code Playgroud)
没有运气.
我们不使用数据库锁,而是使用乐观并发控制来捕获和重试冲突的事务.
目前我们只能看到两个解决方案:
尝试捕获ObjectNotFoundException并尝试智能地逐出集合(尽管在异常中似乎没有足够的上下文)
在items集合上使用@NotFound(action = NotFoundAction.IGNORE)注释,它将忽略而不抛出ObjectNotFoundException(但是我们关注它如何与二级缓存一起工作并确保它正在查看正确的数据) .
我希望能有一个@NotFound(动作= NotFoundAction.EVICT_2ND_LEVEL_CACHE_RELOAD),其中,将驱逐从缓存中的对象,并尝试重新加载集合.
我们也可以尝试改变从懒惰跃跃欲试FetchyType但我想试着去了解问题,并选择将提供在我们的交易数据是在高并发一致的最佳解决方案.