批量查询在线成员对应节点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;
    }
}
相关推荐
夜雪闻竹1 小时前
语义搜索实战:从关键词到向量检索
数据库·知识图谱·ai编程·knowledge graph
GreatSQL社区2 小时前
解决 GreatSQL 报错:存储过程字符集排序规则不兼容问题
数据库
肖有米XTKF86462 小时前
肖有米开发团队:双迹美业水光系统小程序模式
数据库·人工智能·团队开发·csdn开发云
KaMeidebaby2 小时前
卡梅德生物技术快报|多肽库筛选技术构建药物递送功能肽库:流程、算法与质控体
前端·数据库·其他·百度·新浪微博
思麟呀2 小时前
MySQL的视图特性和用户权限管理
数据库·mysql
wljt2 小时前
Redis的5种数据类型
数据库·redis·缓存
敖正炀2 小时前
分布式锁与 Redisson 深度:续期、红锁与无锁化
redis
sakiko_2 小时前
Swift学习笔记30-数据库SQlite语句
数据库·学习·swift
IvorySQL3 小时前
用生成列提升 JSONB 查询效率:PostgreSQL 三种索引方案实测对比
数据库·postgresql