百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

redis专题系列10 -- redis管道技术剖析

mhr18 2024-11-10 09:51 26 浏览 0 评论

Redis是典型的C/S(客户端-服务端模型)架构,底层传输遵循TCP协议,那么一条请求的完整过程如下:

1.客户端通过socket发送请求到服务端,服务端处理请求,客户端阻塞

2.客户端读取socket从服务端的返回结果

即每个命令执行的总时间=客户端发送时间+服务器处理时间+一次网络来回的时间

根据测试,如果客户端和服务端不在一台主机的情况下,网络开销在命令的执行总时间占到很大比重,如果网络不稳定的场景下,一次网络来回的时间是不固定的,在这种情况下,redis的性能很大程度上取决于网络开销。如果我们的服务器每秒可以处理10万条请求,而网络开销是250毫秒,那么实际上每秒钟只能处理4个请求。最暴力的优化方法就是使客户端和服务器在一台物理机上,这样就可以将网络开销降低到1ms以下。但是实际的生产环境我们并不会这样做。而且即使使用这种方法,当请求非常频繁时,这个时间和服务器处理时间比较仍然是很长的。

Redis管道技术的诞生

为了应对这种情况,redis很早就引入了Pipelining技术,即一次性发送多条指令,并一次性返回处理的结果,类似于数据库中的批处理。这样只需要一次网络开销,速度就会得到明显的提升。管道技术其实已经非常成熟并且得到广泛应用了,例如POP3协议由于支持管道技术,从而显著提高了从服务器下载邮件的速度。

在Redis中,如果客户端使用管道发送了多条命令,那么服务器就会将多条命令放入一个队列中,这一操作会消耗一定的内存,所以管道中命令的数量并不是越大越好(太大容易撑爆内存),而是应该有一个合理的值。

深度理解redis一次交互的过程

管道并不只是用来网络开销延迟的一种方法,它实际上是会提升Redis服务器每秒操作总数的。在解释原因之前,需要更深入的了解Redis命令处理过程。

一次完整的详细交互过程如下:

客户端进程调用write()把消息写入到操作系统内核为Socket分配的send buffer中

操作系统会把send buffer中的内容写入网卡,网卡再通过网关路由把内容发送到服务器端的网卡

服务端网卡会把接收到的消息写入操作系统为Socket分配的recv buffer

服务器进程调用read()读取消息然后进行处理

处理完成后调用write()把返回结果写入到服务器端的send buffer

服务器操作系统再将send buffer中的内容写入网卡,然后发送到客户端

客户端操作系统将网卡内容读到recv buffer中

客户端进程调用read()从recv buffer中读取消息并返回

现在我们把命令执行的时间进一步细分:

命令的执行时间 = 客户端调用write并写网卡时间+一次网络开销的时间+服务读网卡并调用read时间++服务器处理数据时间+服务端调用write并写网卡时间+客户端读网卡并调用read时间

这其中除了网络开销,花费时间最长的就是进行系统调用write()和read()了,这一过程需要操作系统由用户态切换到内核态,中间涉及到的上下文切换会浪费很多时间。

使用管道时,多个命令只会进行一次read()和wrtie()系统调用,因此使用管道会提升Redis服务器处理命令的速度,随着管道中命令的增多,服务器每秒处理请求的数量会线性增长。

管道VS脚本

对于管道的大部分应用场景而言,使用Redis脚本(Redis2.6及以后的版本)会使服务器端有更好的表现。使用脚本最大的好处就是可以以最小的延迟读写数据。

有时我们也需要在管道中使用EVAL和EVALSHA命令,这是完全有可能的。因此Redis提供了SCRIPT LOAD命令来支持这种情况。

管道和非管道性能测试案例

有人做过简单的测试,测试条件很宽松,数据仅供参考

测试环境配置:

备注:C/S部署在同一台主机上,服务端使用虚拟机运行,在虚拟机上安装了redis镜像,其他条件一致,使用的java代码,针对string数据类型的get,set操作,结果如下:

来个更直接的折线图对比一下:

当使用了管道后,无论是高频率的存还是取数据,其性能均大大提高,相同条件下,当数据量达到百万级别时,使用管道后性能可提升惊人的200倍以上!当然上面的测试也并非标准严苛的测试,其结果也仅供参考

管道中的命令越多越好吗?

我自同一台机器使用redis-benchmark的测试结果如下:

> redis-benchmark -P 100 -t get,set -q -n 100000

SET: 662251.69 requests per second

GET: 847457.63 requests per second

>redis-benchmark -P 10000 -t get,set -q -n 100000

SET: 144092.22 requests per second

GET: 191938.56 requests per second

从上面的测试中也可以看出,如果一次pipeline组织的命令个数为 10000,但是它对应的QPS 却小于 一次pipeline命令个数为 100的。所以每次组织 Pipeline的命令个数不是越多越好,可以将一次包含大量命令的 Pipeline 拆分为 多个较小的 Pipeline 来完成。

数据量过大造成的问题:

1.增加 客户端等待时间

2.造成一定的网络阻塞

3.占用的内存也会越来越大,容易造成内存撑爆的现象

总结

使用管道技术可以显著提升Redis处理命令的速度,其原理就是将多条命令打包,只需要一次网络开销,在服务器端和客户端各一次read()和write()系统调用,以此来节约时间。

管道能够有效减少用户态和内核态的来回的上下文切换,提高了系统性能

管道中的命令数量要适当,并不是越多越好。

Redis2.6版本以后,脚本在大部分场景中的表现要优于管道。

管道不适用于对命令之间有相互调用的场景,不适用于对数据返回结果有严格要求的场景,适用于对数据要求有一定容错性的场景

最后附两张图加深理解:

相关推荐

说说Redis的单线程架构(redis的单线程模型)

一句话总结Redis采用单线程处理命令请求,避免了多线程的上下文切换和锁竞争,保证原子性操作。其基于内存的高效执行和I/O多路复用模型支撑了高并发性能。网络I/O和持久化操作(如RDB/AOF)由后台...

答记者问之 - Redis 的高效架构与应用模式解析

问:极客程序员你好,请帮我讲一讲redis答:redis主要涉及以下核心,我来一一揭幕Redis的高效架构与应用模式解析Redis是一个开源的内存数据存储系统,因其高性能、丰富的数据结构和易用性...

Redis的5种核心数据结构,及其最经典的“应用场景”

Redis凭什么稳坐缓存界头把交椅?全靠这五个“身怀绝技”的数据结构!在分布式系统的江湖里,Redis就像一位身怀绝技的武林高手,而它的五大核心数据结构正是克敌制胜的五套绝学。今天咱们就来拆解这些独门...

精准定位文件包含漏洞:代码审计中的实战思维

前言最近看到由有分析梦想cms的,然后也去搭建了一个环境看了一看,发现了一个文件包含漏洞的点,很有意思,下面是详细的复现和分析,以后代码审计又多了一中挖掘文件包含漏洞的新思路环境搭建下载https...

ARDM:一款国产跨平台的Redis管理工具

ARDM(AnotherRedisDesktopManager)是一款免费开源的Redis桌面管理客户端,支持Windows、Mac、Linux跨平台。功能特性ARDM提供的主要功能如...

SpringBoot的Web应用开发——Web缓存利器Redis的应用!

 Web缓存利器Redis的应用Redis是目前使用非常广泛的开源的内存数据库,是一个高性能的keyvalue数据库,它支持多种数据结构,常用做缓存、消息代理和配置中心。本节将简单介绍Redis的使...

Windows服务器部署CRMEB开源电商系统,详细教程来了!

安装PHP已经安装过PHP的可以跳过首先安装VC运行库下载地址https://docs.microsoft.com/zh-cn/cpp/windows/latest-supported-vc-redi...

Windows系统下Redis各个安装包介绍与选择指南

简介Redis作为高性能的键值数据库,广泛应用于缓存、消息队列等场景。在Windows系统中部署Redis时,用户可以选择多种安装包以满足不同的需求。本文将详细介绍以下Redis8.0.3版本的安装...

从面试题入手,深度剖析Redis Cluster原理

揭开RedisCluster的神秘面纱**在当今数字化浪潮中,数据量呈爆炸式增长,应用程序对数据存储和处理的要求也日益严苛。Redis作为一款高性能的内存数据库,凭借其出色的读写速度和丰富的数...

给大家推荐些好的c语言代码的网站

C语言,那就来推荐几个吧,部分含有C++:1、TheLinuxKernelArchives(kernel.org)Linux内核源码,仅限于C,但内核庞大,不太适合新手;2、redis(redi...

Redis String 类型的底层实现与性能优化

RedisString是Redis中最基础也是应用最广泛的数据类型,它能存储文本、数字、二进制数据等多种形式的信息。深入理解其底层实现对构建高性能分布式系统至关重要。Redis字符串的底层结...

阿里面试问:Redis 为什么把简单的字符串设计成 SDS?

分享了一道面阿里的redis题,我看了以后觉得挺有意思。题目大致是这样的面试官:了解redis的String数据结构底层实现嘛?铁子:当然知道,是基于SDS实现的面试官:redis是用C语言开发的,那...

编程语言那么多,为何C语言能成为最成功的语言?

编程语言那么多,为何C语言能成为最成功的语言?2025年嵌入式岗位暴增47%,新人却还在问"C语言过时了吗"。真相是连机器人关节驱动都得靠它写,不会指针连芯片手册都看不懂。见过用Pyt...

go-zero 使用 redis 作为 cache 的 2 种姿势

在go-zero框架内,如在rpc的应用service中,其内部已经预置了redis的应用,所以我们只需要在配置中加入相关字段即可,另外,在svcContext声明redisc...

Redis事务深度解析:ACID特性、执行机制与生产实践指南

一、Redis事务的本质与核心机制Redis事务通过MULTI、EXEC、WATCH等命令实现,其本质是将多个命令序列化后一次性执行,而非传统数据库的严格事务模型。核心特点如下:命令队列化:MULT...

取消回复欢迎 发表评论: