Hibernate hazelcast二级缓存不一致

时间:2017-10-30 11:47:16

标签: java hibernate hazelcast second-level-cache

在我们的项目中,我们使用hazelcast 3.6.5作为hibernate(4.3.11)第二个lvl缓存。

以下是描述我们面临的问题的测试:

@Test
public void cacheTest() {

    // Step 1: create account with someValue=111
    Account account = account().withName("test hz account").withSomeValue(111).build();
    account = restClient.upsertAccount(account);

    //Step 2: create user with ref to account
    User user = user().withAccount(account).build();
    restClient.upsertUser(user);

    //Step 3: update account someValue to 222
    account.setSomeValue(222);
    restClient.upsertAccount(account);

    //search users by account id
    List<User> users = restClient.searchUsersByAccountId(BRAND, account.getId());

    assertThat(users.size(), is(1));
    //assertion below fails, user.account.someValue=111
    assertThat(users.get(0).getAccount().getSomeValue(), is(222));
}

测试在具有两个节点的应用程序上运行。以下是请求与不同节点的平衡方式:

node1

172.20.0.1 - - [12:30:46 +0200] "POST /accounts/BRAND/ HTTP/1.1" 200 321
172.20.0.1 - - [12:30:47 +0200] "POST /accounts/BRAND/ HTTP/1.1" 200 321

node2

172.20.0.1 - - [12:30:47 +0200] "POST /users/BRAND/ HTTP/1.1" 200 542
172.20.0.1 - - [12:30:48 +0200] "POST /users/BRAND/search?start=0&limit=1 HTTP/1.1" 200 617

我发现hazelcast 2nd lvl cache包含两个相同帐户的实例 。一个具有旧字段值111,一个具有新字段值222。

首先将实例添加到第一个帐户插入的缓存中,第二个实例添加到用户插入(我们在用户插入时调用帐户)。据我所知,缓存中的这两个帐户实例会导致不一致。

为什么会发生这种情况以及如何调试此问题?

这是数据模型:

@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "accounts")
@Cache(usage = READ_WRITE)
public class Account extends BrandIdEntity {
     @Column(name = "name")
     private String name;

     @Column(name = "some_value")
     private Integer someValue;
}

@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "users")
@Cache(usage = READ_WRITE)
public class User extends BrandIdEntity {

    @Column(name = "account_id")
    private String accountId;

    @ManyToOne(cascade = ALL)
    @JoinColumns({
        @JoinColumn(name = "brand", nullable = false, insertable = false, updatable = false),
        @JoinColumn(name = "account_id", nullable = false, insertable = false, updatable = false) })
    private Account account;
}

@EqualsAndHashCode(of = "pk", callSuper = false)
@MappedSuperclass
public abstract class BrandIdEntity extends AuditedEntity<BrandIdPK> {

    @EmbeddedId
    private final BrandIdPK pk;

    public BrandIdEntity() {
        super();
        pk = new BrandIdPK();
    }

    public BrandIdEntity(BrandType brand, String id, IdGenType idGenType) {
        super();
        pk = new BrandIdPK(brand, id, idGenType);
    }
}

@Embeddable
@Getter
@Setter
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
public class BrandIdPK extends BaseObject {

    @Column(name = "id")
    private String id;

    @Column(name = "brand")
    private String brand;

    public BrandIdPK(BrandType brand, String id, IdGenType idGenType) {
        this.brand = brand.name();
        if (id != null) {
            this.id = id;
        }
        else {
            this.id = next(idGenType);
        }
    }
}

这里是hazelcast map config:

{
   name='com.project.data.Account',
   inMemoryFormat='BINARY',
   backupCount=1,
   asyncBackupCount=0,
   timeToLiveSeconds=300,
   maxIdleSeconds=0,
   evictionPolicy='LRU',
   evictionPercentage=25,
   minEvictionCheckMillis=100,
   maxSizeConfig=MaxSizeConfig{maxSizePolicy='PER_NODE',size=100000},
   readBackupData=true,
   hotRestart=HotRestartConfig{enabled=false,fsync=false},
   nearCacheConfig=null,
   mapStoreConfig=MapStoreConfig{
      enabled=false,className='null',factoryClassName='null',writeDelaySeconds=0,writeBatchSize=1,
      implementation=null,factoryImplementation=null,properties={},
      readOnly=null,initialLoadMode=LAZY,writeCoalescing=true
   },
   mergePolicyConfig='com.hazelcast.map.merge.PutIfAbsentMapMergePolicy',
   wanReplicationRef=null,
   entryListenerConfigs=[],
   mapIndexConfigs=[],
   mapAttributeConfigs=[],
   quorumName=null,
   queryCacheConfigs=[],
   cacheDeserializedValues=INDEX_ONLY
}

0 个答案:

没有答案