redis优化

news2024/11/28 0:53:36

一)优雅的key结构:

redis中的key虽然可以自定义,但是最好遵循下面的几个最佳实践约定:

1)遵循基本格式:业务名称:数据名字:ID;

2)长度不要超过44字节,key所占的字节数越小,占用空间越小,越短越好;

3)不要包含特殊字符;

例如当设计登录业务的时候,保存用户信息,其实可以这样:login:user:10

优点:

1)可读性强

2)避免key的冲突:没有直接使用用户的ID,防止不同的业务之间都使用用户的ID造成key冲突,加上业务名字可以避免业务冲突;

3)方便Key的管理,使用冒号分离,在redis中形成层级结构;

4)更节省内存:key是String类型,底层编码包括int,embstr和raw三种,embstr在小于44字节的时候进行使用,采用连续的内存空间,所占用的内存更小;

查看底层编码:object encoding+key的名字;

int编码:当key是数值的时候进行存储,占用内存空间是非常小的

embstr:是一段连续空间,编码会更加紧凑,占用空间比较小,想要使用ambstr的编码格式,key就需要小于44字节

raw:空间不是连续的,访问性能下降,内存占用会更高,还会产生内存碎片

二)BigKey

在Redis中,一个字符串最大是512MB,一个二级数据结构比如说哈希,list,set,zset可以存储大约40亿个元素,但是实际上如果出现以下几种情况,就被认为是bigKey

1)字符串类型:它的big体现在单个value置很大,一般认为超过10KB就是BigKey

2)非字符串类型:哈希,列表,集合它们的bigKey取决于元素个数太多

memory usage+Key的名字,查看key的大小,但是消耗的CPU资源比较多

针对于String类型来说:strlen key查看key的长度

针对于list集合来说:llen key,查看list集合的长度

三)BigKey的危害: 

1)网络阻塞:针对于BigKey进行网络请求的时候,假设每秒钟对这个bigKey的请求达到了20个,少量的并发就很有可能导致带宽被占满,导致Redis实例乃至所在的物理机变慢,假设这太物理机除了部署redis以外还部署了一些其他的应用,那么会导致其他网络请求被阻塞

2)数据倾斜:BigKey所在的Redis实例内存利用率(数据量)远远超过其他实例,导致无法使数据分片的内存资源达到均衡;

3)Redis阻塞:针对元素比较多的哈希,list,zset等做运算的时候会耗时较久,redis还是单线程的,是主线程被阻塞

4)CPU压力过高:针对BigKey的数据做序列化和反序列化会导致CPU的使用率飙升,影响Redis和本机其他实例的使用

四)排查BigKey:

1)redis-cli --bigKeys,利用redis-cli提供的bigKeys参数,可以遍历分析所有的key,并返回Key的整体统计信息和每一种数据的Top1的big key;

2)scan扫描,利用scan扫描Redis中的所有key,利用strlen或者是hlen等命令来判断key的长度,此处不建议使用memory usage或者是keys *;

2.1)第1个参数是游标,也就是你从第几个位置开始进行扫描,最终redis会返回一个游标,下一次会继续从这个位置进行扫描

2.2)第二个参数你扫描哪一种类型,第三个参数是你要扫描几个

 

@Controller
public class UserController {
    @Autowired
    private Jedis jedis;

    private final int StringMax=10*1024;
    private final int HashMax=500;
    @RequestMapping("/Java100")
    @ResponseBody
    public void scan(){
        System.out.println("1");
        long MaxLen=0;
        long KeyLen=0;
        String cur="0";
       do{
           ScanResult<String> result= jedis.scan(cur);
           //1.记录游标
            cur=result.getCursor();
            //2.获取到扫描的key
            List<String> list=result.getResult();
            if(list==null||list.isEmpty()){
                break;
            }
            for(String key:list){
                System.out.println(key);
                switch(jedis.type(key)){

                    case "string":
                        KeyLen=jedis.strlen(key);
                        MaxLen=StringMax;
                        break;
                    case "hash":
                        KeyLen= jedis.hlen(key);
                        MaxLen=HashMax;
                        break;
                    case "list":
                        KeyLen= jedis.llen(key);
                        MaxLen=HashMax;
                        break;
                    case "set":
                        KeyLen= jedis.scard(key);
                        MaxLen=HashMax;
                        break;
                    case "zset":
                        KeyLen= jedis.zcard(key);
                        MaxLen=HashMax;
                        break;
                }
                if(KeyLen>=MaxLen){
                    System.out.println("当前key是一个bigKey");
                }
            }

        } while(!cur.equals("0"));
    }

}

 五)如何删除BigKey

因为BigKey所占用的内存比较多,那么即便即使删除这样的Key也是很消耗时间的,这样还会导致Redis的主线程阻塞,从而引发一系列问题

1)redis3.0以下版本,比如说hash类型,先借用hdel来删除一个一个的子元素,最后删除key,如果是集合类型,那么先遍历BigKey的子元素,先逐个删除子元素,最后在删除BigKey,还是不能使用keys *,还是使用scan,还是指定key返回一个游标;

 

2)redis4.0以后提供了异步删除的命令,就是unlink命令

恰当的数据类型1:

第一种字符串对象存储方式,修改对应的字段值很不方便,新增字段值也很不方便

第二种转化成更大的key进行存储

1)占用空间比较大,有几个字段,key都是user:1:name,存储了很多相同的key,浪费空间

2)想要获取用户的所有信息比较麻烦

第三种的value又是一个键值对,但是Hash结构的Entry不要超过1000

恰当的数据类型2:

1)当hash的entry数量超过500的时候,会使用哈希表而不是使用ZipList,这样会使内存占用比较多

2)可以通过修改hash-max-ziplist-entries配置entry上限,但是如果entry过多就会导致bigKey问题,但是还是可以通过config set  hash-max-ziplist-entries 1000来进行修改

 

 

解决方案: 

1)转化成String类型进行存储:解决了BigKey的问题

1.1)String类型底层结构没有太多优化,内存占用比较多

1.2)想要批量获取这些数据比较麻烦

2)拆分成小的hash,将id/100作为key,将id%100作为field,这样每100个元素为一个hash,解决了BigKey的问题;

 

 

 批处理优化:

一次命令的执行时间:1次往返的网络传输耗时+1次redis的执行命令的耗时,网络传输是非常耗时的,但是也不需要在一次批处理中传输太多命令,否则单次命令占用网络带宽过多导致网络阻塞

 

 

mset虽然可以进行批处理,但是却只能操作部分数据类型,如果对有复杂数据类型的批处理需要,需要使用管道来进行处理

1)m操作是redis原生提供的操作,这个操作的执行是原子性的,一次性会直接全部执行完成,中间过程中不会有其他命令来进行插队

2)但是管道是直接讲这些命令发送到管道里面,但是不会一起执行,因为管道里面命令的传输是有先后顺序的,在命令传输的过程中也是可以有其他客户端来给redis传输命令的,管道的命令会进入到redis队列中排队,redis的线程会依次取出这些命令进行执行,如果有其他命令来插队,那么实际执行时长可能会比与其执行时长要长

 

 

集群下的批处理:

批处理是在一次连接中把所有的请求全部干掉,如mset或者是Pipeline这样的批处理需要在一次请求中携带多条命令,而如果此时Redis是一个集群,那么批处理得key必须落到同一个插槽中,否则就会执行失败;

mset、mget只支持在同一个槽内的key,因为不在一个槽内的key可能存在于不同节点上

服务器端的优化:

1)用来做缓存的redis尽量不要使用持久化功能;

2)建议关闭RDB持久化功能,使用AOF持久化功能;

3)利用脚本定期在slave节点做RDB,来实现数据备份;

4)设置合理的rewrite阈值,避免频繁的重写

5)配置no-appendfsyc-on-rewrite:yes,禁止在AOF重写的过程中做AOF持久化,避免因为AOF引起的阻塞

不建议redis和做大量CPU密集型计算的应用和高磁盘负载的应用部署到同一台服务器上

慢查询:

 

下面的例子就是假设执行了keys *命令,接下来就可以通过showlog get 1来查询对应的命令

 

 bind表示可以访问所有可以访问redis的服务器

 

这个配置是把config命令替换成后面的命令 

redis内存配置:

当redis内存不足的时候,可能会导致key频繁被删除,响应时间变长等问题,当redis的内存使用频率超过90%以上就需要我们警惕,并应该快速定位到内存占用的原因

1)数据内存,这是redis最主要的部分,用来存储redis的键值信息,主要的问题是BigKey问题,内存碎片的问题,是在内存分配的过程中产生的,当向redis中存储一部分的数据的时候,假设存储10个字节,就会分配16个字节,多分配给的6个字节就是内存碎片,要想解决内存碎片问题,就可以解决内存碎片的问题;

2)进程内存:Redis主进程本身运行肯定需要占用内存,比如说代码和常量池等等,这部分内存大约几兆,在大多数生产环境中和Redis数据占用的内存相比可以忽略

3)缓冲区内存:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/577097.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

this 内存原理

&#x1f49f;这里是CS大白话专场&#xff0c;让枯燥的学习变得有趣&#xff01; &#x1f49f;没有对象不要怕&#xff0c;我们new一个出来&#xff0c;每天对ta说不尽情话&#xff01; &#x1f49f;好记性不如烂键盘&#xff0c;自己总结不如收藏别人&#xff01; &#x1f…

Spring Cloud Alibaba - Nacos

目录 一、Spring Cloud Alibaba 1、简介 二、Nacos 1、Nacos介绍 2、什么是Nacos&#xff1f; 3、为何使用Nacos&#xff1f; 4、Nacos下载和安装 4.1、启动 Linux/Unix/Mac Windows 5、Nacos代替Eureka 6、Nacos服务注册中心 一、Spring Cloud Alibaba Spring Cl…

【循环自相关和循环谱系列7】OFDM循环自相关推导分析、时间参数估计原理仿真及某无人机实际图传信号验证(含矩形/非矩形、有无循环前缀等情况)

重要声明:为防止爬虫和盗版贩卖,文章中的核心代码可凭【CSDN订阅截图或公z号付费截图】私信免费领取,一律不认其他渠道付费截图! 说明:本博客含大量公式推导分析,比较烧脑,需要有一定的数学基础,高等数学、信号与系统等! 这是循环自相关和循环谱系列的第七篇文章了…

基于SpringBoot+Vue测试用例管理系统

✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取项目下载方式&#x1f345; 一、项目背景介绍&#xff1a; 随着信息技术的不断发…

【Vue】学习笔记-Vue中的Ajax配置代理

回顾 常用的发送Ajax请求的方法有哪些&#xff1f; xhr​​ new XMLHttpRequest() xhr.open()、xhr.send()(真正开发中很少用到&#xff0c;太麻烦了&#xff0c;我们一般使用的都是他的二次封装) ​jQuery​​ 其对xhr有二次封装 . g e t ( ) 、 .get()、 .get()、.post ​…

【一起啃书】《机器学习》第八章集成学习

文章目录 第八章 集成学习8.1 个体与集成8.2 Boosting8.3 Bagging与随机森林8.4 结合策略8.5 多样性 第八章 集成学习 8.1 个体与集成 集成学习通过构建并结合多个学习器来完成学习任务&#xff0c;有时也被称为多分类器系统、基于委员会的学习等&#xff0c;下面是集成学习的…

Mac下好用的日记、电子书阅读器、RSS订阅软件​

Mac下好用的日记笔记本、电子书阅读器和RSS订阅、播客订阅等软件推荐。我们收录到 Mac下好用的日记、电子书阅读器、RSS订阅软件​http://www.webhub123.com/#/home/detail?pLZPL-2ofIu 收录效果如下 ​也可以使用分组视图来查看各类软件网址 ​ 登录后可一键保存全部软件网址…

Java 集合 - Queue 接口

文章目录 1.Queue 接口2.LinkedList3.ArrayDeque4.PriorityQueue5.总结 队列是一种特殊的线性数据结构&#xff0c;在数据的尾部插入元素&#xff0c;在数据的头部删除元素。通常以 FIFO&#xff08;先进先出&#xff09;的方式存储和访问数据。Java 中提供了 Queue 接口来实现…

element-ui对话框dialog详解

效果展示 先给大家展示一下大致的样式 代码 <el-dialog draggable destroy-on-close v-model"dialogAddVisible" title"添加用户" width"35%" center><el-form :inline"true" :model"addFormInfo" status-icon …

Java中的String数据类型,String类(字符串)详解

目录 第一章、String概述1&#xff09;String是什么2&#xff09;String长什么样3&#xff09;String的构造方法(声明方式) 第二章、String类的详解1&#xff09;String底层是什么2&#xff09;字符串存储的内存原理/字符串常量池(String Constant Pool&#xff09;3&#xff0…

C语言-【指针二】-【指针运算/指针和数组】

好久不见吖&#xff0c;好啦&#xff0c;言归正传&#xff0c;这篇文章接着上篇文章的尾巴接着介绍指针相关知识哦&#xff01; 一.指针运算 &#xff08;1&#xff09;指针-整数 &#xff08;2&#xff09;指针-指针 &#xff08;3&#xff09;指针的关系运算 接下来&…

Apache Kafka - 高性能原因探究

文章目录 概述图解 概述 Kafka 的高性能主要依赖于以下几个关键因素: 分布式架构:Kafka 采用分布式集群架构,可以水平扩展到上万个节点,支持每秒处理百万级消息。持久化存储:Kafka 使用文件系统持久化存储消息,避免了数据库成为性能瓶颈,大大提高了吞吐量。顺序读写:Kafka 的…

计算机视觉:卷积核的运行过程

本文重点 我们前面从直观角度理解了卷积神经网络的卷积在特征提取的作用,本节课程我们从数学角度来看一下,卷积是如何计算的? 计算步骤 1. 将卷积核与输入图像的某一部分进行逐元素相乘。 2. 将相乘后的结果求和,得到卷积核在该部分的输出值。 3. 重复以上步骤,将卷积核…

达梦8逻辑备份导出导入dexp/dimp

逻辑导出&#xff08;dexp&#xff09;和逻辑导入&#xff08;dimp&#xff09;是 DM 数据库的两个命令行工具&#xff0c;分别用来实现对 DM 数据库的逻辑备份和逻辑还原。逻辑备份和逻辑还原都是在联机方式下完成&#xff0c;联机方式是指数据库服务器正常运行过程中进行的备…

数据结构作业4-图

图数据结构的小练习&#xff1a; 文章目录 数据结构作业4-图3 对图1所示的带权无向图。&#xff08;40分&#xff09;解&#xff1a; 4 对于图1所示的带权无向图。&#xff08;20分&#xff09;解&#xff1a; 5 已知带权有向图如下图所示&#xff0c;请利用Dijkstra算法从顶点…

基于操作系统的基础IO

1.c语言中的文件输入输出 在观看本章节的时候&#xff0c;大家可以去看看之前c语言的文件输入输出的有关博客。 好那么废话不多说之间进入本章正题: 我们都知道c程序默认会打开三个输入输出流&#xff1a; stdin&#xff1a;相当于键盘 stdout&#xff1a;相当于显示器 st…

【Linux】基本指令(四)

目录 &#x1f348;一.sort指令&#x1f348; &#x1f349;二.uniq指令&#x1f349; &#x1f34a;三.wc指令&#x1f34a; &#x1f34b;四.which指令&#x1f34b; &#x1f34e;五.whereis指令&#x1f34e; &#x1f34f;六.top指令&#x1f34f; &#x1f350;七…

【玩转 Cloud Studio】腾讯Cloud Studio 云端开发环境上手体验

目录 1、Cloud Studio简介 2、功能体验 3、Cloud Studio优点 4、总结 1、Cloud Studio简介 Cloud Studio&#xff08;云端 IDE&#xff09;是基于浏览器的集成式开发环境&#xff0c;为开发者提供了一个稳定快速的云端工作站。用户在使用 Cloud Studio 时无需安装&#xff0c;只…

【LCD应用编程】绘制点、线、矩形框

之前获取LCD屏幕参数信息时了解到&#xff0c;LCD屏是 FrameBuffer 设备&#xff0c;操作 FrameBuffer 设备 其实就是在读写 /dev/fb0 文件。除此之外&#xff0c;LCD屏上包含多个像素点&#xff0c;绘制点、线、矩形框本质是在修改这些像素点的颜色。 目录 1、定义 lcd_color…

VS+Qt — Vistual Studio 2022+Qt6安装教程以及解决Qt Vistual Studio Tools下载慢和VS无法打开.ui进行设计的问题

目录 Vistual Studio 2022下载 Qt下载 Qt Vistual Studio Tools下载 方法1 方法2 方法3 方法4 Vistual Studio 2022配置Qt6 创建Qt项目 若VS无法打开.ui进行设计 Vistual Studio 2022下载 以前因为安装库的关系&#xff0c;已经下载过VS2022了&#xff0c;详细请看这…