批量查询在线成员对应节点redis

java 复制代码
package com.kongjs.im.message.service;


import com.alibaba.fastjson2.JSON;
import com.kongjs.im.common.dto.UserDeviceOnlineDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;


import java.util.*;

@Slf4j
@Service
public class ImOnlineService {

    private static final String USER_ONLINE = "im:online:device:{%s}";

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 【同步非响应式】
     * 批量获取多个用户的 完整在线设备信息(Hash 全量数据)
     *
     * @param userIds 用户ID列表
     * @return Map<userId, Map<deviceId, UserDeviceOnlineDTO>>
     */
    public Map<Long, Map<String, UserDeviceOnlineDTO>> batchGetUserOnlineInfo(List<Long> userIds) {
        if (userIds == null || userIds.isEmpty()) {
            return Collections.emptyMap();
        }
        // 1. 构建批量 KEY
        List<String> keys = new ArrayList<>();
        for (Long userId : userIds) {
            keys.add(String.format(USER_ONLINE, userId));
        }
        // 2. Lua 脚本:批量 hgetall
        DefaultRedisScript<List<List<String>>> script = new DefaultRedisScript<>();
        script.setScriptText("""
                    local result = {}
                    for i = 1, #KEYS do
                        local data = redis.call('HGETALL', KEYS[i])
                        table.insert(result, data)
                    end
                    return result
                """);
        //script.setResultType(List.class);
        // 3. 执行 Lua(同步)
        List<List<String>> rawResult = stringRedisTemplate.execute(script, keys);
        // 4. 解析结果
        Map<Long, Map<String, UserDeviceOnlineDTO>> finalMap = new HashMap<>(rawResult.size());
        for (int i = 0; i < userIds.size(); i++) {
            Long userId = userIds.get(i);
            List<String> hashData = rawResult.get(i);
            Map<String, UserDeviceOnlineDTO> deviceMap = new HashMap<>();
            for (int j = 0; j < hashData.size(); j += 2) {
                String deviceId = hashData.get(j);
                String json = hashData.get(j + 1);
                // JSON 转你的 DTO
                UserDeviceOnlineDTO dto = null;
                try {
                    dto = JSON.parseObject(json, UserDeviceOnlineDTO.class);
                } catch (Exception e) {
                    log.error("{}", e.getMessage());
                }
                if (dto != null) {
                    deviceMap.put(deviceId, dto);
                }
            }
            finalMap.put(userId, deviceMap);
        }
        return finalMap;
    }
}
相关推荐
流星白龙7 分钟前
【Redis】1.Redis特性
数据库·redis·缓存
奶糖 肥晨10 分钟前
DBeaver 安装与 MySQL 连接配置教程
数据库·mysql
woshihuanglaoshi29 分钟前
数据迁移与版本管理 - Flutter在鸿蒙平台实现数据库升级策略
数据库·学习·flutter·华为·harmonyos·鸿蒙·鸿蒙系统
java_logo2 小时前
Apache Doris Docker 部署指南:实时分析数据库实战
数据库·docker·apache·doris·apache doris·轩辕镜像·docker部署doris
广州灵眸科技有限公司10 小时前
xfce桌面触摸校准:基于灵眸科技EASY-EAl-Orin-Nano
数据库·windows·科技
憧憬成为web高手13 小时前
皮卡丘靶场速通--sql 2
数据库·sql·mybatis
段一凡-华北理工大学13 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
二宝哥14 小时前
CentOS 7.9 系统下 Redis 5.0.4 单机安装与源码编译安装指南
redis·centos
oradh15 小时前
Oracle XTTS实现跨版本迁移和升级(Oracle 11g单库升级至19C RAC集群)
数据库·oracle·11g升级19c·xtts跨版本迁移和升级
z1234567898616 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程