Hibernate Hazelcast事件队列重载更新缓存区域默认更新时间戳区域

Hibernate Hazelcast事件队列重载更新缓存区域默认更新时间戳区域,hibernate,hazelcast,Hibernate,Hazelcast,我最近添加了一个新的工作线程,它将队列排入不同的表中,然后退出。在跑步时,我看到了很多follow日志信息 2021-05-16 11:25:19.496 WARN 18 --- [Thread-1] com.hazelcast.spi.EventService : [127.0.0.1]:5701 [dev] [3.12.6] EventQueue overloaded! TopicEvent{name='default-update-timestamps-region'

我最近添加了一个新的工作线程,它将队列排入不同的表中,然后退出。在跑步时,我看到了很多follow日志信息

2021-05-16 11:25:19.496  WARN 18 --- [Thread-1] com.hazelcast.spi.EventService           : [127.0.0.1]:5701 [dev] [3.12.6] EventQueue overloaded! TopicEvent{name='default-update-timestamps-region', publishTime=1621164319495, publisherAddress=[172.18.0.4]:5701} failed to publish to hz:impl:topicService:default-update-timestamps-region
表中没有缓存我正在读取/写入的实体,所以我想知道为什么缓存会在这个线程上刷新,更不用说它是如何突破这个事件队列的限制的了

我还没有更改配置的默认值(使用Hazelcast 3.12.6),所以我很困惑这怎么会如此迅速地使缓存水合

请参阅下面我的新服务的粗略伪代码

private void processForever() {
    threadRef = Thread.currentThread();
    synchronized (syncObject) {
        //notify init that we're good to continue
        syncObject.notifyAll();
    }
    while (threadRef == Thread.currentThread()) {
        boolean foundWork = false;
        try {
            foundWork = process();
        } catch (Exception e) {
            log.debug("stack", e);
        }

        long sleep = foundWork ? 1000 : 60000;
        try {
            Thread.sleep(sleep);
        } catch (InterruptedException e) {

        }
    }
}

private boolean process() {
    try {
        // N.B this attempts to grab a shared lock on the current tenant and skips of already taken
        return dataGrid.runExclusiveForCurrentTenantOrSkip(LockName.PROCESS, this::processInternal).orElse(true);
    } catch (Exception ex) {
        log.error("error", ex);
        return true;
    }
}

private boolean processInternal() {
    Long maxSid = sourceQueueRepo.findMaxSid();
    if (maxSid == null) {
        return false;
    }

    Set<Worker> agents = workerRepo.findAllWorkers();
    queueWork(maxSid, agents);

    return true;
}

public void queueWork(Long maxId, Set<Worker> workers) {

    sourceQueueRepo.dedupeByMaxSid(maxId);

    List<SourceQueue> batch = sourceQueueRepo.findAllBySidLessThanEqual(maxId);
    Map<Long, List<SourceQueue>> batched = // Redacted

    for (Worker worker : workers) {
        // Method 'batchInsert' calls a save query (transactional)
        batchInsert(worker, batched.getOrDefault(Type.TYPE_1, new HashMap<>()));
        batchInsert(worker, batched.getOrDefault(Type.TYPE_2, new HashMap<>()));
        batchInsert(worker, batched.getOrDefault(Type.TYPE_3, new HashMap<>()));
    }


    sourceQueueRepo.deleteByMaxId(maxId);
}
private void processForever(){
threadRef=Thread.currentThread();
已同步(同步对象){
//通知init我们可以继续
syncObject.notifyAll();
}
while(threadRef==Thread.currentThread()){
布尔foundWork=false;
试一试{
foundWork=过程();
}捕获(例外e){
调试(“堆栈”,e);
}
长睡眠=基础工作?1000:60000;
试一试{
睡眠;
}捕捉(中断异常e){
}
}
}
私有布尔进程(){
试一试{
//注意:此操作试图获取当前租户的共享锁,并跳过已获取的共享锁
返回dataGrid.runExclusiveForcurrentTenantTorSkip(LockName.PROCESS,this::processInternal).orElse(true);
}捕获(例外情况除外){
日志错误(“错误”,ex);
返回true;
}
}
私有布尔processInternal(){
Long maxSid=sourceQueueRepo.findMaxSid();
if(maxSid==null){
返回false;
}
Set agents=workerRepo.findAllWorkers();
队列工作(maxSid、代理);
返回true;
}
public void queueWork(Long maxId,Set worker){
sourceQueueRepo.dedupeByMaxSid(maxId);
List batch=sourceQueueRepo.findAllBySidLessThanEqual(maxId);
映射批处理=//已编辑
用于(工人:工人){
//方法“batchInsert”调用保存查询(事务性)
batchInsert(worker,batched.getOrDefault(Type.Type_1,new HashMap());
batchInsert(worker,batched.getOrDefault(Type.Type_2,new HashMap());
batchInsert(worker,batched.getOrDefault(Type.Type_3,new HashMap());
}
sourceQueueRepo.deleteByMaxId(maxId);
}
注意

  • 每个查询都是事务性的,其目标是保持数据库事务简短,因为目标表上的其他线程可能存在争用
  • 插入此队列的代码在此新线程上调用中断,以确保其正在排空新队列。有多个线程调用此函数,因此重载下的停机时间很少

我追踪到了要使用的问题,我的新线程承受了很大的压力,缓存区域在传播事件时淹没了事件队列

我选择不切换到使用,因为对于我的场景,这对性能产生了不可接受的影响

相反,对于
@Modifying
查询,我选择使用NativeQuery对象,并通过
addSynchronizedEntityClass
指定要使其失效的缓存项

例如,



返回em.createNativeQuery(“DELETE FROM dbo.SourceQueue,其中id来自我所看到的-运行上述代码似乎正在更新所有实体的缓存(偶尔会看到此日志消息中列出的一些实体),对于此操作,我不依赖任何缓存实体或查询

return em.createNativeQuery("DELETE FROM dbo.SourceQueue WHERE id <= :id")
    .unwrap(NativeQuery.class)
    .setParameter("id", id)
    .addSynchronizedEntityClass(SourceQueue.class)
    .executeUpdate();