亳州位置汇聚改动

ds-suzhou
luyya 2026-04-15 15:06:46 +08:00
parent 8443d5e58f
commit be599f9768
4 changed files with 75 additions and 43 deletions

View File

@ -31,5 +31,4 @@ public class EsGpsInfo implements Serializable {
private Integer online;
}

View File

@ -8,6 +8,7 @@ import org.dromara.common.core.utils.RedisConstants;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.data2es.controller.DataToEsController;
import org.dromara.data2es.domain.EsGpsInfoVO2;
import org.dromara.data2es.service.IGpsService;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RTopic;
@ -22,6 +23,7 @@ import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.net.InetSocketAddress;
import java.time.Duration;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
@ -32,7 +34,9 @@ public class RedisExpireListener extends KeyExpirationEventMessageListener {
private final RedisExpireRecoveryHandler recoveryHandler;
@Autowired
DataToEsController dataToEsController;
IGpsService gpsService;
private volatile boolean active = true;
public RedisExpireListener(
@ -89,8 +93,9 @@ public class RedisExpireListener extends KeyExpirationEventMessageListener {
RLock lock = redisson.getLock("LOCK:" + expiredKey);
try {
if (lock.tryLock(0, 30, TimeUnit.SECONDS)) {
// 实际业务逻辑
// 等待5秒获取锁确保集群中只有一个实例处理
if (lock.tryLock(5, 30, TimeUnit.SECONDS)) {
try {
String[] split = expiredKey.split(":");
String deviceType = split[2];
String deviceCode = split[3];
@ -100,6 +105,21 @@ public class RedisExpireListener extends KeyExpirationEventMessageListener {
return;
}
// 检查1过期key如果重新存在了说明有新数据刷新不处理离线
boolean exists = RedisUtils.isExistsObject(expiredKey);
if (exists) {
log.info("过期key已刷新跳过离线处理: {}", expiredKey);
return;
}
// 检查2设置处理标记防止其他实例重复处理标记保留60秒
String processedKey = "PROCESSED:" + expiredKey;
boolean isNew = RedisUtils.setObjectIfAbsent(processedKey, "1", Duration.ofSeconds(60));
if (!isNew) {
log.info("已被其他实例处理,跳过: {}", expiredKey);
return;
}
log.info("处理过期Key: {}", expiredKey);
JSONObject object = RedisUtils.getBucket(RedisConstants.ONLINE_USERS + deviceType + ":" + deviceCode);
@ -110,19 +130,29 @@ public class RedisExpireListener extends KeyExpirationEventMessageListener {
}
EsGpsInfoVO2 gpsInfo = BeanUtil.toBean(object, EsGpsInfoVO2.class);
// 检查3如果已经是离线状态不重复处理
if (gpsInfo.getOnline() != null && gpsInfo.getOnline() == 0) {
log.info("设备已离线,跳过重复处理: {}", expiredKey);
return;
}
gpsInfo.setOnline(0);
dataToEsController.saveGpsInfo(gpsInfo);
gpsService.updateOnlineStatus(gpsInfo);
log.info("处理完成: key={}", expiredKey);
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
} else {
log.info("获取锁超时,可能其他实例正在处理: {}", expiredKey);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
log.error("处理过期事件被中断", e);
} catch (Exception e) {
log.error("处理过期事件异常", e);
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}

View File

@ -165,14 +165,17 @@ public class RequestHandler {
long b = RedisUtils.geoAdd(Double.valueOf(esGpsInfoVo2.getLng()),
Double.valueOf(esGpsInfoVo2.getLat()), deviceCode +"#"+ deviceType);
if(onlineTime > 0) {
// 只有在线状态才设置过期监听key离线状态不设置避免循环触发过期事件
if(onlineTime > 0 && (esGpsInfoVo2.getOnline() == null || esGpsInfoVo2.getOnline() == 1)) {
//设置一个过期时间方便key自动过期监听设置离线 [RedisExpireListener]
RedisUtils.set(RedisConstants.ONLINE_USERS_TEN +
deviceType
+ ":" + deviceCode, jsonValue, onlineTime);
} else if (esGpsInfoVo2.getOnline() != null && esGpsInfoVo2.getOnline() == 0) {
// 离线状态删除过期监听key
RedisUtils.del(RedisConstants.ONLINE_USERS_TEN +
deviceType
+ ":" + deviceCode);
}
//方便根据组织机构计算数量