当前位置: 首页 > news >正文

Redis实践

Redis实践

使用复杂度高的命令

如果在使用Redis时,发现访问延迟突然增大,如何进行排查?

首先,第一步,建议你去查看一下Redis的慢日志。Redis提供了慢日志命令的统计功能,我们通过以下设置,就可以查看有哪些命令在执行时延迟比较大。

首先设置Redis的慢日志阈值,只有超过阈值的命令才会被记录,这里的单位是微妙,例如设置慢日志的阈值为5毫秒,同时设置只保留最近1000条慢日志记录:

# 命令执行超过5毫秒记录慢日志
CONFIG SET slowlog-log-slower-than 5000
# 只保留最近1000条慢日志
CONFIG SET slowlog-max-len 1000

设置完成之后,所有执行的命令如果延迟大于5毫秒,都会被Redis记录下来,我们执行SLOWLOG get 5​查询最近5条慢日志:

127.0.0.1:6379> SLOWLOG get 5
1) 1) (integer) 32693       # 慢日志ID2) (integer) 1593763337  # 执行时间3) (integer) 5299        # 执行耗时(微妙)4) 1) "LRANGE"           # 具体执行的命令和参数2) "user_list_2000"3) "0"4) "-1"
2) 1) (integer) 326922) (integer) 15937633373) (integer) 50444) 1) "GET"2) "book_price_1000"
...

通过查看慢日志记录,我们就可以知道在什么时间执行哪些命令比较耗时,如果你的业务经常使用O(n)以上复杂度的命令,例如sort​、sunion​、zunionstore​,或者在执行O(n)命令时操作的数据量比较大,这些情况下Redis处理数据时就会很耗时。

如果你的服务请求量并不大,但Redis实例的CPU使用率很高,很有可能是使用了复杂度高的命令导致的。

存储大key

如果查询慢日志发现,并不是复杂度较高的命令导致的,例如都是SET​、DELETE​操作出现在慢日志记录中,那么你就要怀疑是否存在Redis写入了大key的情况。

Redis在写入数据时,需要为新的数据分配内存,当从Redis中删除数据时,它会释放对应的内存空间。

如果一个key写入的数据非常大,Redis在分配内存时也会比较耗时。同样的,当删除这个key的数据时,释放内存也会耗时比较久

你需要检查你的业务代码,是否存在写入大key的情况,需要评估写入数据量的大小,业务层应该避免一个key存入过大的数据量。

那么有没有什么办法可以扫描现在Redis中是否存在大key的数据吗?

Redis也提供了扫描大key的方法:

redis-cli -h <span class="katex--inline"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>h</mi><mi>o</mi><mi>s</mi><mi>t</mi><mo>−</mo><mi>p</mi></mrow><annotation encoding="application/x-tex">host -p </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"><span class="mord mathnormal">h</span><span class="mord mathnormal">os</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2222em;"><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"><span class="mord mathnormal">p</span></span></span></span></span>port --bigkeys -i 0.01
</span></span></span></span>

使用上面的命令就可以扫描出整个实例key大小的分布情况,它是以类型维度来展示的。

需要注意的是当我们在线上实例进行大key扫描时,Redis的QPS会突增,为了降低扫描过程中对Redis的影响,我们需要控制扫描的频率,使用i​参数控制即可,它表示扫描过程中每次扫描的时间间隔,单位是秒。

使用这个命令的原理,其实就是Redis​在内部执行scan​命令,遍历所有key​,然后针对不同类型的key​执行strlen​、llen​、hlen​、scard​、zcard​来获取字符串的长度以及容器类型(list/dict/set/zset)​的元素个数。

而对于容器类型的key,只能扫描出元素最多的key​,但元素最多的key​不一定占用内存最多,这一点需要我们注意下。不过使用这个命令一般我们是可以对整个实例中key​分布情况有比较清晰的了解。

针对大key​的问题,Redis​官方在4.0版本推出了lazy-free​的机制,用于异步释放大key​的内存,降低对Redis​性能的影响。

即使这样,我们也不建议使用大key,大key在集群的迁移过程中,也会影响到迁移的性能

集中过期

有时你会发现,平时在使用Redis​时没有延时比较大的情况,但在某个时间点突然出现一波延时,而且报慢的时间点很有规律,例如某个整点,或者间隔多久就会发生一次。

如果出现这种情况,就需要考虑是否存在大量key集中过期的情况。

如果有大量的key在某个固定时间点集中过期,在这个时间点访问Redis时,就有可能导致延迟增加。

解决方案是,在集中过期时增加一个随机时间,把这些需要过期的key的时间打散即可

伪代码可以这么写:

# 在过期时间点之后的5分钟内随机过期掉
redis.expireat(key, expire_time + random(300))

实例内存达到上限

有时我们把Redis当做纯缓存使用,就会给实例设置一个内存上限maxmemory​,然后开启LRU淘汰策略。

当实例的内存达到了maxmemory​后,你会发现之后的每次写入新的数据,有可能变慢了。

导致变慢的原因是,当Redis内存达到maxmemory​后,每次写入新的数据之前,必须先踢出一部分数据,让内存维持在maxmemory​之下。

这个踢出旧数据的逻辑也是需要消耗时间的,而具体耗时的长短,要取决于配置的淘汰策略:

  • allkeys-lru:不管key是否设置了过期,淘汰最近最少访问的key
  • volatile-lru:只淘汰最近最少访问并设置过期的key
  • allkeys-random:不管key是否设置了过期,随机淘汰
  • volatile-random:只随机淘汰有设置过期的key
  • allkeys-ttl:不管key是否设置了过期,淘汰即将过期的key
  • noeviction:不淘汰任何key,满容后再写入直接报错
  • allkeys-lfu:不管key是否设置了过期,淘汰访问频率最低的key(4.0+支持)
  • volatile-lfu:只淘汰访问频率最低的过期key(4.0+支持)

我们最常使用的一般是allkeys-lru​或volatile-lru​策略,它们的处理逻辑是,每次从实例中随机取出一批key​(可配置),然后淘汰一个最少访问的key​,之后把剩下的key​暂存到一个池子中,继续随机取出一批key​,并与之前池子中的key​比较,再淘汰一个最少访问的key​。以此循环,直到内存降到maxmemory​之下。

如果使用的是allkeys-random​或volatile-random​策略,那么就会快很多,因为是随机淘汰,那么就少了比较key​访问频率时间的消耗了,随机拿出一批key​后直接淘汰即可,因此这个策略要比上面的LRU​策略执行快一些。

fork耗时严重

如果你的Redis开启了自动生成RDB和AOF重写功能,那么有可能在后台生成RDB和AOF重写时导致Redis的访问延迟增大,而等这些任务执行完毕后,延迟情况消失。

遇到这种情况,一般就是执行生成RDB和AOF重写任务导致的。

生成RDB​和AOF​都需要父进程fork​出一个子进程进行数据的持久化,在fork​执行过程中,父进程需要拷贝内存页表给子进程,如果整个实例内存占用很大,那么需要拷贝的内存页表会比较耗时,此过程会消耗大量的CPU​资源,在完成fork​之前,整个实例会被阻塞住,无法处理任何请求,如果此时CPU​资源紧张,那么fork​的时间会更长,甚至达到秒级。这会严重影响Redis​的性能。

我们可以执行info​命令,查看最后一次fork​执行的耗时latest_fork_usec​,单位微妙。这个时间就是整个实例阻塞无法处理请求的时间。

要想避免这种情况,我们需要规划好数据备份的周期,建议在从节点上执行备份,而且最好放在低峰期执行。如果对于丢失数据不敏感的业务,那么不建议开启RDB​和AOF​重写功能。

另外,fork的耗时也与系统有关,如果把Redis部署在虚拟机上,那么这个时间也会增大。所以使用Redis时建议部署在物理机上,降低fork的影响。

使用Swap

如果你发现Redis突然变得非常慢,每次访问的耗时都达到了几百毫秒甚至秒级,那此时就检查Redis​是否使用到了Swap​,这种情况下Redis​基本上已经无法提供高性能的服务。

我们知道,操作系统提供了Swap机制,目的是为了当内存不足时,可以把一部分内存中的数据换到磁盘上,以达到对内存使用的缓冲。

但当内存中的数据被换到磁盘上后,访问这些数据就需要从磁盘中读取,这个速度要比内存慢太多!

尤其是针对Redis这种高性能的内存数据库来说,如果Redis中的内存被换到磁盘上,对于Redis这种性能极其敏感的数据库,这个操作时间是无法接受的。

我们需要检查机器的内存使用情况,确认是否确实是因为内存不足导致使用到了Swap​。

如果确实使用到了Swap​,要及时整理内存空间,释放出足够的内存供Redis​使用,然后释放Redis​的Swap​,让Redis​重新使用内存。

释放Redis​的Swap​过程通常要重启实例,为了避免重启实例对业务的影响,一般先进行主从切换,然后释放旧主节点的Swap​,重新启动服务,待数据同步完成后,再切换回主节点即可。

可见,当Redis​使用到Swap​后,此时的Redis​的高性能基本被废掉,所以我们需要提前预防这种情况。

我们需要对Redis机器的内存和Swap使用情况进行监控,在内存不足和使用到Swap时及时报警出来,及时进行相应的处理

网卡负载过高

特点就是从某个时间点之后就开始变慢,并且一直持续。这时你需要检查一下机器的网卡流量,是否存在网卡流量被跑满的情况。

网卡负载过高,在网络层和TCP层就会出现数据发送延迟、数据丢包等情况。Redis的高性能除了内存之外,就在于网络IO,请求量突增会导致网卡负载变高。

相关文章:

Redis实践

Redis实践 使用复杂度高的命令 如果在使用Redis时&#xff0c;发现访问延迟突然增大&#xff0c;如何进行排查&#xff1f; 首先&#xff0c;第一步&#xff0c;建议你去查看一下Redis的慢日志。Redis提供了慢日志命令的统计功能&#xff0c;我们通过以下设置&#xff0c;就…...

【Lora模型推荐】Stable Diffusion创作具有玉石翡翠质感的图标设计

站长素材AI教程是站长之家旗下AI绘图教程平台 海量AI免费教程&#xff0c;每日更新干货内容 想要深入学习更多AI绘图教程&#xff0c;请访问站长素材AI教程网&#xff1a; AI教程_深度学习入门指南 - 站长素材 (chinaz.com) logo版权归各公司所有&#xff01;本笔记仅供AIGC…...

vscode 远程开发

目录 vscode 远程连接 选择 Python 环境 vscode 远程连接 按 CtrlShiftP 打开命令面板。输入并选择 Remote-SSH: Open SSH Configuration File...。选择 ~/.ssh/config 文件&#xff08;如果有多个选项&#xff09;。在打开的文件中添加或修改你的 SSH 配置。 这个可以右键…...

前端Vue组件化实践:打造灵活可维护的地址管理组件

随着前端技术的不断演进&#xff0c;复杂度和开发难度也随之上升。传统的一体化开发模式使得每次小小的修改或功能增加都可能牵一发而动全身&#xff0c;严重影响了开发效率和维护成本。组件化开发作为一种解决方案&#xff0c;通过模块化、独立化的开发方式&#xff0c;实现了…...

虚幻引擎ue5游戏运行界面白茫茫一片,怎么处理

根剧下图顺序即可调节游戏运行界面光照问题&#xff1a; 在大纲里找到post&#xff0c;然后选中它&#xff0c;找到Exposure 把最低亮度和最高亮度的0改为1即可...

《代理选择与反爬虫策略探究:如何优化网络爬虫效率与稳定性》

代理IP如何选以及常见反爬策略 为什么需要代理&#xff1f; 因为有的网站会封IP&#xff0c;用户如果没有登录&#xff0c;那IP就是身份标识&#xff0c;如果网站发现用户行为异常就非常可能封IP 什么是代理IP 就是让一个人帮你转交请求&#xff0c;帮你转交的人对面不熟&a…...

Kotlin Flow 防抖 节流

防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案。 一:防抖&#xff08;debounce&#xff09;的概念&#xff1a; 防抖是指当持续触发事件时&#xff0c;一定时间段内没有再触发事件&#xff0c;事件处理函数才会执行一次&#xff0c; 如果设定时间到来之前&#x…...

Android Studio下载与安装

Android Studio下载与安装_android studio下载安装-CSDN博客...

【LC刷题】DAY24:122 55 45 1005

122. 买卖股票的最佳时机 II class Solution { public:int maxProfit(vector<int>& prices) {int result 0;for(int i 1; i < prices.size(); i ){result max(prices[i] - prices[ i - 1], 0);}return result;} };55. 跳跃游戏 link class Solution { public…...

从零开始的python学习生活2

接上封装 class Phone:__volt0.5def __keepsinglecore(self):print("让cpu以单核运行")def if5G(self):if self.__volt>1:print("5G通话已开启")else:self.__keepsinglecore()print("电量不足&#xff0c;无法使用5G通话&#xff0c;已经设置为单…...

【并发编程】进程 线程 协程

进程&#xff08;Process&#xff09;、线程&#xff08;Thread&#xff09;和协程&#xff08;Coroutine&#xff09;构成了计算机科学中实现任务并发执行的三种核心抽象机制。通常&#xff0c;为了提高程序的执行效率&#xff0c;开发者会根据应用场景和性能需求&#xff0c;…...

Vue的生命周期函数有哪些?详细说明

Vue.js 的生命周期函数包括以下几个阶段&#xff0c;每个阶段都有相应的钩子函数可以用来在特定时机执行自定义的逻辑。这些生命周期钩子函数使得我们可以在组件的不同阶段进行操作&#xff0c;从而管理组件的状态和行为。 1. beforeCreate&#xff1a; - 描述&#xff1a;…...

大语言模型应用--AI工程化落地

文章目录 大语言模型概述什么是大语言模型什么是机器学习什么是深度学习 理解大语言模型历史沿革关键 AIGC系统AI工程化项目的落地落地的方法Prompt工程&#xff08;第一阶段&#xff09;RAG检索&#xff08;第二阶段&#xff09;训练特定功能模型&#xff08;第三阶段&#xf…...

我会什么开发技能

java我会什么&#xff1f; 一、并发编程 1、并发编程&#xff1a;jdk中的courren包只能够类实现&#xff08;seamplore&#xff0c;CountDownLaunch&#xff0c;Pharse&#xff0c;CycliBarrier&#xff0c;CompletableFuture&#xff09;&#xff0c;AQS的原理&#xff0c;线…...

Run LoongArch64 Alpine VM on x86_64

一、Build from source(build on x86_64) Obtain the latest libvirt, virt-manager, and qemu source code, compile and install them. 1.1 Build libvirt from source sudo apt-get update sudo apt-get install augeas-tools bash-completion debhelper-compat dh-apparm…...

4层负载均衡和7层负载均衡

四层负载均衡&#xff08;Layer 4 Load Balancing&#xff09;指的是在网络传输层&#xff08;TCP/IP模型中的第四层&#xff09;进行负载均衡的技术。四层负载均衡通常使用IP地址、端口号和协议等信息来将网络流量分配到多个服务器上。它主要关心网络层的信息&#xff0c;不涉…...

前端Vue组件化实践:打造仿京东天猫商品属性选择器组件

在前端开发领域&#xff0c;随着业务需求的日益复杂和技术的不断进步&#xff0c;传统的整体式应用开发模式已逐渐显得捉襟见肘。面对日益庞大的系统&#xff0c;每次微小的功能修改或增加都可能导致整个逻辑结构的重构&#xff0c;形成牵一发而动全身的困境。为了解决这一问题…...

智慧城市3d数据可视化系统提升信息汇报的时效和精准度

在信息大爆炸的时代&#xff0c;数据的力量无可估量。而如何将这些数据以直观、高效的方式呈现出来&#xff0c;成为了一个亟待解决的问题。为此&#xff0c;我们推出了全新的3D可视化数据大屏系统&#xff0c;让数据“跃然屏上”&#xff0c;助力您洞察先机&#xff0c;决胜千…...

Git 详解(原理、使用)

git 快速上手请看这篇博客 Git 快速上手 1. 什么是 Git Git 是目前最主流的一个版本控制器&#xff0c;并且是分布式版本控制系统&#xff0c;可以控制电脑上所有格式的文档 版本控制器&#xff1a;记录每次修改以及版本迭代的管理系统 对于文本文件&#xff0c;可以记录每次…...

android11为开机动画添加铃声(语音)

一、碰到的问题 1、第一次开机无铃声 2、开机时铃声和动画不同步&#xff0c;开头的铃声会丢失 3、开机时铃声/动画不能完全播放完 二、解决 以下为添加的patch /开机铃声不同步&#xff0c;语音第一段无声 diff --git a/media/libmediaplayerservice/MediaPlayerService…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

安卓基础(aar)

重新设置java21的环境&#xff0c;临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的&#xff1a; MyApp/ ├── app/ …...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用

前言&#xff1a;我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM&#xff08;Java Virtual Machine&#xff09;让"一次编写&#xff0c;到处运行"成为可能。这个软件层面的虚拟化让我着迷&#xff0c;但直到后来接触VMware和Doc…...

Qt/C++学习系列之列表使用记录

Qt/C学习系列之列表使用记录 前言列表的初始化界面初始化设置名称获取简单设置 单元格存储总结 前言 列表的使用主要基于QTableWidget控件&#xff0c;同步使用QTableWidgetItem进行单元格的设置&#xff0c;最后可以使用QAxObject进行单元格的数据读出将数据进行存储。接下来…...