众所周知,所有数据存放在内存,读写延迟低,能够满足毫秒级访问。那么Redis就满足了我们的这一需求。Redis 提供 String、Hash、List、Set、Sorted Set 等多种结构,本文则选择了其中的 Hash,其非常适合存储本项目中结构化的设备状态信息。
(项目简介:多台设备需要实现每30秒上报心跳数据,Redis存储每台设备的在线状态、最后心跳等信息,其结构大致如:Key: device:status Field: {device_id} Value: JSON 或 二进制序列化后的对象,包含在线状态、最后心跳时间等 example:HSET device:status device123 '{"online": true, "last_heartbeat": 24060118001}')
一、嵌入式设备端实现 (Java)
嵌入式设备端(如网关或终端)也可以直接使用 Jedis 客户端定时向 Redis 缓存发送心跳和状态信息。以下示例演示如何在设备上使用定时任务定期上报:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class EmbeddedDeviceHeartbeat {
private static final String DEVICE_ID = "embedded-device-001";
private static final DeviceStatusCache cache = new DeviceStatusCache("localhost", 6379);
public static void main(String[] args) {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(() -> {
try {
cache.cacheStatus(DEVICE_ID, true);
} catch (Exception e) {
e.printStackTrace();
}
}, 0, 30, TimeUnit.SECONDS);
}
}
二、写入流程
Map<String, Object> info = new HashMap<>();
info.put("online", true);
info.put("last_heartbeat", System.currentTimeMillis() / 1000);
jedis.hset("device:status", deviceId, mapper.writeValueAsString(info));
这样单个写入显然不可取,于是给出批量写入
Pipeline pipeline = jedis.pipelined();
for (String id : batchIds) {
Map<String, Object> info = new HashMap<>();
info.put("online", true);
info.put("last_heartbeat", System.currentTimeMillis() / 1000);
pipeline.hset("device:status", id, mapper.writeValueAsString(info));
}
pipeline.sync();
三、读取流程
String json = jedis.hget("device:status", deviceId);
Map<String, Object> status = mapper.readValue(json, Map.class);
批量读取:
List<String> jsonList = jedis.hmget("device:status", deviceIds.toArray(new String[0]));
for (int i = 0; i < deviceIds.size(); i++) {
if (jsonList.get(i) != null) {
statuses.put(deviceIds.get(i), mapper.readValue(jsonList.get(i), Map.class));
}
}
四、过期策略
由于 Hash 不支持对单个 Field 设置 TTL,常见替代策略:
1.整 Key 设置过期:如每日清除。
cache.initExpireForHashKey(86400); // 24小时后过期
2.ZSet 辅助记录心跳时间:按时间戳排序,定期移除超时设备。
3.逻辑过期:在 Value 中嵌入过期时间,读取时判断是否过期。