# device-list **Repository Path**: hcy_0120/device-list ## Basic Information - **Project Name**: device-list - **Description**: java重构服务... - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-04-02 - **Last Updated**: 2026-04-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # device-list-service-java `device-list-service-go` 的 Java 迁移版本,使用: - Spring Boot 2.7.x - JDK 8 - Spring AMQP - Spring Kafka - Spring Integration MQTT - Spring Data Redis - MyBatis Annotation - Caffeine Cache ## 目标 第一阶段目标是对 Go 版现有业务逻辑做 1:1 迁移: - RabbitMQ 五条队列消费 - `homeAlive/+` MQTT 订阅 - Redis `STATUS:PUBLISH` 订阅 - `mac -> homeId`、`homeId -> 家庭主机mac`、家庭活跃度、本地聚合集合等本地缓存 - 家庭设备列表写 Redis - 设备变动 Kafka 推送 - 看板全量设备状态 Kafka 推送 ## 目录 - `src/main/java/com/gree/iot/devicelist/config`: Spring 配置 - `src/main/java/com/gree/iot/devicelist/cache`: 本地缓存 - `src/main/java/com/gree/iot/devicelist/dto`: DTO - `src/main/java/com/gree/iot/devicelist/mapper`: MyBatis 注解 Mapper - `src/main/java/com/gree/iot/devicelist/service`: 业务服务 - `src/main/java/com/gree/iot/devicelist/listener`: 消息监听器 - `src/main/java/com/gree/iot/devicelist/scheduler`: 定时任务 ## 说明 - 消息中间件接法采用 Java/Spring 标准实现,不强行复刻 Go 的底层 API 使用方式。 - 业务语义、Redis 键结构、SQL 查询逻辑、时间窗口和消息体结构按 Go 版本保持对齐。 - Go 仓库中 `InitKafkaConsumer()` 未提供实现,Java 版当前保留为 no-op,并明确记录。 - 当前环境缺少 `java` / `javac` / `mvn`,本仓库尚未完成本地编译验证。 - 更细的静态审查记录见 `STATIC_REVIEW.md`。 ## 最新优化 ### 1. RabbitMQ 拓扑消息改为 Redis 分布式去重 Java 版当前保留了单实例内 `3s` 聚合刷新设备列表到 Redis 的设计,同时把“是否把 homeId 发到 Kafka”这一层去重改成了 Redis 原子去重: - 使用 `SET key value NX PX ttl` 等价语义 - key 形如 `HOMEID:DEDUP:{homeId}` - 默认去重窗口 `3000ms` 这样同一个 `homeId` 在多个 Pod 同时消费到时,只有第一个拿到 Redis 去重令牌的实例会继续发送 Kafka,下游不会再被重复 `homeId` 打穿。 ### 2. 主机设备与家庭关系改为 Redis + Caffeine 两级缓存 当前 Java 版对 `homeId -> 家庭主机mac`、`mac -> homeId` 这类高频读取关系采用: - Redis 作为共享事实源 - Caffeine 作为本地热点缓存 读取顺序是: `Caffeine -> Redis -> DB` 命中 Redis 或 DB 后会立即回填本地缓存。 ### 3. 使用 RabbitMQ 广播保证本地缓存最终一致 为了保证多 Pod 下本地 Caffeine 不会长期持有旧的主机映射关系,当前实现新增了一个 fanout exchange 做缓存同步广播。 设计上采用“广播失效而不是广播写入”的策略: - 当前实例先更新 Redis - 再广播一条本地缓存失效消息 - 其他实例收到后仅删除本地缓存 - 下次访问时再从 Redis 回填 这样可以避免多实例下由于消息乱序把旧值重新写回本地缓存。