批量查询在线成员对应节点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;
    }
}
相关推荐
海南java第二人8 小时前
Nebula Graph 实战:基于图数据库存储 CMDB 实体关系
数据库·图数据库·nebula
曹牧8 小时前
oracle:“not all variables bound”
数据库·oracle
数据库百宝箱8 小时前
Oracle RMAN Image Copy 本地恢复
数据库·oracle
轻刀快马8 小时前
Redis 架构进阶:全景解析 RDB、AOF 与混合持久化机制
redis
zuYM4g7Dp9 小时前
NoSql数据库设计心得
数据库·nosql
睡不醒男孩03082311 小时前
第七篇:揭秘 PostgreSQL 数据库内核级管控:CLup 深度架构设计与高可用底座技术白皮书
数据库·postgresql·clup
cmes_love12 小时前
Level 2逐笔成交历史数据下载方法笔记
数据库·笔记·oracle
swordbob12 小时前
MySQL字符集陷阱:从Oracle迁移踩坑到utf8mb4强制规范
数据库·sql
牛油果子哥q12 小时前
【C++ STL string 】C++ STL string 终极精讲:底层原理、内存机制、全套API、深浅拷贝、易错坑点与工程实战规范
数据库·c++
十五年专注C++开发12 小时前
MySql中各种功能用sql语句实现总结
数据库·sql·mysql