redis key以目录展示的算法 以及其他redis相关

2023-10-26


前言

一般在开发中使用redis时,都会使用冒号进行key的分割,例如login_token:admin等等,最近被要求编写可视化redis管理的工具,要以树形文件夹目录展示redis中的所有key,正文内容如下。


一、redis相关

要获取redis中的所有key,一般用的都是keys *进行匹配获取,但这个命令会造成阻塞和加锁,在数据量较大的生产环境使用比较危险,因而使用scan代替,相关的具体理论请自行搜索。相关代码如下:

	/**
     * 通过游标遍历redis中的key
     * 每10000条一次 这里不是只执行一次 游标的移动已被封装
     * 真正执行查询的语句在cursor.hasNext()中 具体可看源码
     */
    public Set<String> scan(String pattern){
        Set<String> keys = new HashSet<>();
        RedisSerializer<?> serializer = redisTemplate.getKeySerializer();
        ScanOptions scanOptions = ScanOptions.scanOptions().match(pattern).count(10000).build();
        try (Cursor<byte[]> cursor = redisTemplate.execute(connection -> connection.scan(scanOptions), true)) {
            if (null == cursor){
                return keys;
            }
            while (cursor.hasNext()) {
                keys.add(String.valueOf(serializer.deserialize(cursor.next())));
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return keys;
    }

额外记录一下redis获取内存使用量的代码。

	/**
     * 获取key对应的内存使用量
     * @param key key
     * @return long
     */
    public Long memoryUsage(String key){
        try {
            RedisConnectionFactory connectionFactory = redisTemplate.getConnectionFactory();
            if (null != connectionFactory){
                String usageScript = "return redis.pcall('MEMORY', 'USAGE', KEYS[1])";
                Long result = connectionFactory.getConnection().eval(
                        usageScript.getBytes(StandardCharsets.UTF_8),
                        ReturnType.INTEGER,
                        1,
                        key.getBytes(StandardCharsets.UTF_8));
                if (null == result){
                    return 0L;
                }
                return result;
            }
            return 0L;
        }catch (Exception e){
            e.printStackTrace();
            return 0L;
        }
    }

二、目录展示算法

前端使用的树形组件为ztree,如果要使用其他的前端组件需要自己更改返回格式,需要的数据为list,如图,以id和pId关联子父级。

	/**
     * 标记key分割的结束符号
     */
    private final String splitEndSign = "}]>T^T<[{";

    /**
     * key中的分隔符
     */
    private final String splitSign = ":";	

	/**
     * 将redis中查出的keu加载为树形结构
     * @param allKey key集合
     * @return 树list
     */
    private List<Ztree> initZtree(Set<String> allKey){
        List<Ztree> ztrees = new LinkedList<>();
        Map<String, Object> treeMap = new HashMap<>();
        long start = System.currentTimeMillis();
        allKey.forEach(key -> {
            String[] keyArray = key.split(splitSign);
            List<String> list = new ArrayList<>(keyArray.length);
            Collections.addAll(list, keyArray);
            // 根据分隔符切割key构造基于map的树形结构
            initTreeMap(treeMap, list);
        });
        // 转换为树结构
        treeMaptoZtree(ztrees, treeMap, null, null);
        log.debug("构造树结构花费:{}毫秒", (System.currentTimeMillis() - start));
        log.debug("构造树结长度为:{}条", ztrees.size());
        return ztrees;
    }

	/**
     * 构造基于map的树形结构
     * @param treeMap 树map
     * @param list 分割后的key的list
     */
    private void initTreeMap(Map<String, Object> treeMap, List<String> list) {
        // 根据key获取或设置指向的map
        Object obj = treeMap.computeIfAbsent(list.get(0), k -> new HashMap<>());
        // 如果list的长度大于1说明还没结束 移除掉当前的值并进行递归
        if (list.size() > 1){
            list.remove(0);
            initTreeMap((Map<String, Object>) obj, list);
        }else {
            // 否则加入结束的标志 表示此key已经结束
            treeMap.put(list.get(0) + splitEndSign, null);
        }
    }

	/**
     * 将treeMap转换为树结构 交予前端组件展示
     */
    private void treeMaptoZtree (List<Ztree> ztrees, Map<String, Object> treeMap, String pid, String parentKey){
        // 防止重复key
        Set<String> repeatKeyCheck = new HashSet<>();
        // 遍历treeMap
        treeMap.forEach((key, value) -> {
            // 唯一id用于标识父子关系
            String uuid = IdUtil.fastSimpleUUID();
            if (null != value && ((Map<String, Object>) value).size() > 0){
                Ztree ztree = new Ztree();
                String wholeKey;
                // 如果parentKey不为空则不是key的开头 开始构造key的完整值
                if (null != parentKey){
                    wholeKey = parentKey + splitSign + key;
                }else {
                    wholeKey = key;
                }
                ztree.setTitle(wholeKey);
                ztree.setName(key);
                ztree.setpId(pid);
                ztree.setId(uuid);
                ztrees.add(ztree);
                // 还没有结束则继续递归
                treeMaptoZtree(ztrees, (Map<String, Object>) value, uuid, wholeKey);
            }else {
                String orgiKey = key;
                // 如果key以结束符结尾 则去除结束符在进行下一步操作
                if (key.endsWith(splitEndSign)){
                    orgiKey = key.substring(0, key.length() - splitEndSign.length());
                }
                // 如果key没有被添加过 进行后续操作
                if (!repeatKeyCheck.contains(orgiKey)){
                    repeatKeyCheck.add(orgiKey);
                    Ztree ztree = new Ztree();
                    if (null != parentKey){
                        ztree.setTitle(parentKey + splitSign + orgiKey);
                    }else {
                        ztree.setTitle(orgiKey);
                    }
                    ztree.setName(orgiKey);
                    ztree.setpId(pid);
                    ztree.setId(uuid);
                    ztree.setIslast(true);
                    ztrees.add(ztree);
                }
            }
        });
    }

结果展示

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

redis key以目录展示的算法 以及其他redis相关 的相关文章

  • 如何使用 Apache POI API 将图像添加到 pptx 中添加的图像占位符?

    我已经预定义了带有文本和图像占位符的 pptx 模板 我如何从模板访问和修改这些占位符 我可以使用 POI pptx API 直接将图像和文本添加到幻灯片中 但如何将其添加到模板的占位符中 请参阅链接以了解如何添加占位符来创建固定模板 ht
  • 如何使用 Java 中的 Web 服务(例如 Axis2)发送复杂对象的数组或集合?

    我对 SOAP Web 服务还比较陌生 虽然我完成了一些较小的 Web 服务项目 但我偶然从来不需要返回 或用作参数 复杂 对象的数组或集合 当我尝试这样做时 根据我的 SOAP 绑定风格 我会得到不同的奇怪行为 当我使用RPC 文字 我可
  • 如何创建一个显示 Spinners 的 x 和 y 值的表格?

    我想创建一个位于图表右侧的表格 其中显示 2 列 x 和 y 值已输入到xSpin and ySpin旋转器 我已经画了一张我想要桌子放置的位置的图 我尝试过在网格窗格布局中使用文本框来创建表格并将值直接输入到文本框网格中 但是我无法将它们
  • SAML 服务提供商 Spring Security

    当使用预先配置的服务提供者元数据时 在 Spring Security 中 是否应该有 2 个用于扩展元数据委托的 bean 定义 一份用于 IDP 元数据 一份用于 SP 元数据
  • Android在排序列表时忽略大小写

    我有一个名为路径的列表 我目前正在使用以下代码对字符串进行排序 java util Collections sort path 这工作正常 它对我的 列表进行排序 但是它以不同的方式处理第一个字母的情况 即它用大写字母对列表进行排序 然后用
  • OSGi:如果不取消服务会发生什么

    这是我获取 OSGi 服务的方式 ServiceReference reference bundleContext getServiceReference Foo class getName Foo foo Foo bundleContex
  • Java AES 128 加密方式与 openssl 不同

    我们遇到了一种奇怪的情况 即我们在 Java 中使用的加密方法会向 openssl 生成不同的输出 尽管它们在配置上看起来相同 使用相同的键和 IV 文本 敏捷的棕色狐狸跳过了懒狗 加密为 Base64 字符串 openssl A8cMRI
  • JavaFX 中具有自定义内容的 ListView

    How i can make custom ListView with JavaFx for my app I need HBox with image and 2 Labels for each line listView 您可以通过查看
  • 如何在不超过最大值的情况下增加变量?

    我正在为学校开发一个简单的视频游戏程序 我创建了一个方法 如果调用该方法 玩家将获得 15 点生命值 我必须将生命值保持在最大值 100 并且由于我目前的编程能力有限 我正在做这样的事情 public void getHealed if h
  • Calendar.getInstance(TimeZone.getTimeZone("UTC")) 不返回 UTC 时间

    我对得到的结果真的很困惑Calendar getInstance TimeZone getTimeZone UTC 方法调用 它返回 IST 时间 这是我使用的代码 Calendar cal Two Calendar getInstance
  • Java 8 流 - 合并共享相同 ID 的对象集合

    我有一系列发票 class Invoice int month BigDecimal amount 我想合并这些发票 这样我每个月都会收到一张发票 金额是本月发票金额的总和 例如 invoice 1 month 1 amount 1000
  • 使用 SQLITE 按最近的纬度和经度坐标排序

    我必须获得一个 SQLite SQL 语句 以便在给定初始位置的情况下按最近的纬度和经度坐标进行排序 这是我在 sqlite 数据库中的表的例句 SELECT id name lat lng FROM items EXAMPLE RESUL
  • Java 中的“Lambdifying”scala 函数

    使用Java和Apache Spark 已用Scala重写 面对旧的API方法 org apache spark rdd JdbcRDD构造函数 其参数为 AbstractFunction1 abstract class AbstractF
  • 很好地处理数据库约束错误

    再一次 它应该很简单 我的任务是在我们的应用程序的域对象中放置一个具有唯一约束的特定字段 这本身并不是一个很大的挑战 我刚刚做了以下事情 public class Location more fields Column unique tru
  • Javafx过滤表视图

    我正在尝试使用文本字段来过滤表视图 我想要一个文本字段 txtSearch 来搜索 nhs 号码 名字 姓氏 和 分类类别 我尝试过在线实施各种解决方案 但没有运气 我对这一切仍然很陌生 所以如果问得不好 我深表歉意 任何帮助将不胜感激 我
  • HQL Hibernate 内连接

    我怎样才能在 Hibernate 中编写这个 SQL 查询 我想使用 Hibernate 来创建查询 而不是创建数据库 SELECT FROM Employee e INNER JOIN Team t ON e Id team t Id t
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • 如何使用 JSch 将多行命令输出存储到变量中

    所以 我有一段很好的代码 我很难理解 它允许我向我的服务器发送命令 并获得一行响应 该代码有效 但我想从服务器返回多行 主要类是 JSch jSch new JSch MyUserInfo ui new MyUserInfo String
  • ServletContainer 类未找到异常

    我无法再编译我的球衣项目 并且出现以下异常 GRAVE Servlet Project API threw load exception java lang ClassNotFoundException com sun jersey spi
  • 如何从 Maven 存储库引用本机 DLL?

    如果 JAR 附带 Maven 存储库中的本机 DLL 我需要在 pom xml 中放入什么才能将该 DLL 放入打包中 更具体地举个例子Jacob http search maven org artifactdetails 7Cnet s

随机推荐

  • Allegro PCB设计小诀窍系列--如何把PCB板上的线变成铜皮

    背景介绍 我们在进行PCB设计时 经常需要从其他软件导入图形 比如用其他软件绘制完成的防静电标识等 Allegro软件对于图形的描述是矢量的 而有很多软件对大块图形的描述是线性的 这就导致这类图形导入到Allegro之后 图形是由一条条的线
  • 独家

    作者 Faizan Shaikh 翻译 季洋 校对 王雨桐 本文约2700字 建议阅读10 分钟 本文将展示如何使用开源工具完成一个人脸识别的算法 引言 计算机视觉和机器学习已经开始腾飞 但是大多数人并不清楚计算机在识别一张图片的时候 它到
  • C语言宏定义嵌套容易出错,难道是C的Bug?

    今天的HDU上面做题 4501题的时候本想嵌套一个宏 简单一点 但是调试好久都不行 就是输出不对 后来改成函数就可以了 define max x y x
  • 8.9数据结构作业

    队列头文件 ifndef HTLINKLIST H define HTLINKLIST H typedef int datatype typedef struct Node union datatype data int len struc
  • vs2017运行显示系统找不到指定的文件_十分钟学会win10系统封装-封装

    Easy Sysprep将封装分为了两个阶段 第一阶段 以完成封装操作为首要目的 第二阶段 以完成对系统的调整为首要目的 将封装与调整分开 减少调整操作对封装操作的影响 保障封装成功率 第一阶段 在C盘目录下新建文件夹Sysprep 拷贝万
  • javaScript获取cookie转换成json

    原始转换 function cookie to json var cookie text document cookie var arr var text to split cookie text split for var i in te
  • AcWing 756. 蛇形矩阵

    题目 输入两个整数n和m 输出一个n行m列的矩阵 将数字 1 到 n m 按照回字蛇形填充至矩阵中 具体矩阵形式可参考样例 输入格式 输入共一行 包含两个整数n和m 输出格式 输出满足要求的矩阵 矩阵占n行 每行包含m个空格隔开的整数 数据
  • 天梯赛 一至十二届题解合集(最简洁规范题解)

    l1和l2已全部更新完毕 l3更新大概1 3 有更好的解法的大佬请在评论区指出 题解 第一届 点我 题解 第二届 点我 题解 第三届 点我 题解 第四届 点我 题解 第五届 点我 题解 第六届 点我 题解 第七届 点我 题解 第八届 点我
  • (网络安全数据集一)美国国家安全漏洞库 NVD-CVE信息解读 和常用漏洞库

    NVD中CVE信息解读 最近要用到这方面的数据 就对NVD中的一小段CVE信息选取做了简单的理解 有错的地方请大佬指正 一个完整的CVE信息 包含 六部分 元数据 漏洞影响软件信息 漏洞问题类型 参考和漏洞介绍 configurations
  • Spring Boot 中的 @SendTo 注解

    Spring Boot 中的 SendTo 注解 在 Spring Boot 中 SendTo 注解是一个非常有用的注解 它可以用于实现 WebSocket 的消息转发功能 本文将介绍 SendTo 注解的原理 使用方法和示例代码 什么是
  • Sophus库:对SO(3)和SE(3)的构建及扰动模型搭建

    简介 使用Eigen库中Geometry模块能够实现对 S O 3 SO 3 SO 3 S
  • 微信开发者工具的版本控制

    注意事项 拉取代码时 应先关闭所有的编辑器代码页面 清理版本管理工具里的工作区 保存到本地 不管什么时候 需要把代码提交到线上的请先拉取一下线上代码 一 提交代码流程 先在 微信开发者工具 的 版本管理 中把代码存储在本地分支上 拉取线上分
  • 用js实现简单的满屏跳动的心

    用js实现简单的满屏跳动的心
  • 实施MES系统的成功率只有50%,你知道为什么吗?

    MES系统可以称之为生产制造产业生产和管理方法实现代化的管理中心 假如可以非常好的执行和运用MES 那么将有益于提升公司的生产率 降低消耗成本 但为什么会有些公司MES执行实际效果不佳呢 原因之一 我国制造业存在管理方法基础的先天发育不足
  • Android中LCD背光驱动

    分类 Linux驱动 Android系统 2013 06 17 16 28 287人阅读 评论 0 收藏 举报 目录 Android的Setting Android的背光JNI层 Android的背光HAL层 Linux的背光内核层 Lin
  • 【web基础】html常用标签+作品展示

    前言 小亭子正在努力的学习编程 接下来将开启javaEE的学习 分享的文章都是学习的笔记和感悟 如有不妥之处希望大佬们批评指正 同时如果本文对你有帮助的话 烦请点赞关注支持一波 感激不尽 说明 此部分是java web基础知识 学的不深 仅
  • python爬虫万能模板

    以下是一个简单的 Python 爬虫模板 可以用于爬取网页数据 python import requests from bs4 import BeautifulSoup 设置请求头 模拟浏览器访问 headers User Agent Mo
  • kubectl命令详解

    目录 一 kubectl命令详解 1 查看某个资源的详细信息 kubectl describe pod pod name n nameapace 2 查看指定命名空间中pod的基本信息 kubectl get pods n namespac
  • kubernetes自建单节点elasticsearch ,用做数据库

    apiVersion v1 kind ConfigMap metadata name es configmap namespace kube system data elasticsearch yml cluster name NAMESP
  • redis key以目录展示的算法 以及其他redis相关

    文章目录 前言 一 redis相关 二 目录展示算法 结果展示 前言 一般在开发中使用redis时 都会使用冒号进行key的分割 例如login token admin等等 最近被要求编写可视化redis管理的工具 要以树形文件夹目录展示r