【存储中间件】Redis核心技术与实战(一):Redis入门与应用(常用数据结构:字符串String、哈希Hash、列表List)

devtools/2025/3/14 9:41:57/

文章目录

  • Redis入门与应用
    • Redis常用数据结构
      • 字符串(String)
        • 操作命令
          • set 设置值
          • get 获取值
          • mset 批量设置值
          • mget 批量获取值
          • Incr 数字运算
          • append追加指令
          • strlen 字符串长度
          • getset 设置并返回原值
          • setrange 设置指定位置的字符
          • getrange 截取字符串
        • 命令的时间复杂度
        • 使用场景
      • 哈希(Hash)
        • 操作命令
          • hset设值
          • hget取值
          • hdel删除field
          • hlen计算field个数
          • hmset批量设值
          • hmget批量取值
          • hexists判断field是否存在
          • hkeys获取所有field
          • hvals获取所有value
          • hgetall获取所有field与value
          • hincrby增加
          • hstrlen 计算value的字符串长度
        • 命令的时间复杂度
        • 使用场景
      • 列表(list)
        • 操作命令
          • lrange 获取指定范围内的元素列表(不会删除元素)
          • rpush 向右插入
          • lpush 向左插入
          • linsert 在某个元素前或后插入新元素
          • lpop 从列表左侧弹出(会删除元素)
          • rpop 从列表右侧弹出
          • lrem 对指定元素进行删除
          • ltirm 按照索引范围修剪列表
          • lset修改指定索引下标的元素
          • lindex 获取列表指定索引下标的元素
          • llen 获取列表长度
          • blpop和brpop阻塞式弹出元素
        • 使用场景

在这里插入图片描述
个人主页:道友老李
欢迎加入社区:道友老李的学习社区

Redis入门与应用

Redis常用数据结构

Redis提供了一些数据结构供我们往Redis中存取数据,最常用的的有5种,字符串(String)、哈希(Hash)、列表(list)、集合(set)、有序集合(ZSET)。

字符串(String)

字符串类型是Redis最基础的数据结构。首先键都是字符串类型,而且其他几种数据结构都是在字符串类型基础上构建的,所以字符串类型能为其他四种数据结构的学习奠定基础。字符串类型的值实际可以是字符串(简单的字符串、复杂的字符串(例如JSON、XML))、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB。

(虽然Redis是C写的,C里面有字符串<本质使用char数组来实现>,但是处于种种考虑,Redis还是自己实现了字符串类型)

操作命令
set 设置值

set key valueimage.png

set命令有几个选项:

ex seconds: 为键设置秒级过期时间。

px milliseconds: 为键设置毫秒级过期时间。

nx: 键必须不存在,才可以设置成功,用于添加(分布式锁常用)。

xx: 与nx相反,键必须存在,才可以设置成功,用于更新。

image.png

从执行效果上看,ex参数和expire命令基本一样。还有一个需要特别注意的地方是如果一个字符串已经设置了过期时间,然后你调用了set 方法修改了它,它的过期时间会消失。

而nx和xx执行效果如下

image.png

除了set选项,Redis 还提供了setex和 setnx两个命令:

setex key
seconds value

setnx key value

setex和 setnx的作用和ex和nx选项是一样的。也就是,setex为键设置秒级过期时间,setnx设置时键必须不存在,才可以设置成功。

setex示例:

image.png

setnx示例:

image.png

因为键foo-ex已存在,所以setnx失败,返回结果为0,键foo-ex2不存在,所以setnx成功,返回结果为1。

有什么应用场景吗?以setnx命令为例子,由于Redis的单线程命令处理机制,如果有多个客户端同时执行setnx key value,根据setnx的特性只有一个客户端能设置成功,setnx可以作为分布式锁的一种实现方案。当然分布式锁没有不是只有一个命令就OK了,其中还有很多的东西要注意,我们后面会用单独的章节来讲述基于Redis的分布式锁。

get 获取值

如果要获取的键不存在,则返回nil(空):

image.png

mset 批量设置值

通过mset命令一次性设置4个键值对

image.png

mget 批量获取值

image.png

批量获取了键a、b、c、d的值:

如果有些键不存在,那么它的值为nil(空),结果是按照传入键的顺序返回。

批量操作命令可以有效提高效率,假如没有mget这样的命令,要执行n次get命令具体耗时如下:

n次 get时间=n次网络时间+n次命令时间

使用mget命令后,要执行n次get命令操作具体耗时如下:

n次get时间=1次网络时间+n次命令时间

Redis可以支撑每秒数万的读写操作,但是这指的是Redis服务端的处理能力,对于客户端来说,一次命令除了命令时间还是有网络时间,假设网络时间为1毫秒,命令时间为0.1毫秒(按照每秒处理1万条命令算),那么执行1000次 get命令需要1.1秒(10001+10000.1=1100ms),1次mget命令的需要0.101秒(11+10000.1=101ms)。

Incr 数字运算

incr命令用于对值做自增操作,返回结果分为三种情况:

值不是整数,返回错误。

值是整数,返回自增后的结果。

键不存在,按照值为0自增,返回结果为1。

image.png

除了incr命令,Redis提供了decr(自减)、 incrby(自增指定数字)、decrby(自减指定数字)、incrbyfloat(自增浮点数),具体效果请同学们自行尝试。

append追加指令

append可以向字符串尾部追加值

image.png

strlen 字符串长度

返回字符串长度

image.png

注意:每个中文占3个字节

getset 设置并返回原值

getset和set一样会设置值,但是不同的是,它同时会返回键原来的值

image.png

setrange 设置指定位置的字符

image.png

下标从0开始计算。

getrange 截取字符串

getrange 截取字符串中的一部分,形成一个子串,需要指明开始和结束的偏移量,截取的范围是个闭区间。

image.png

命令的时间复杂度

字符串这些命令中,除了del 、mset、 mget支持多个键的批量操作,时间复杂度和键的个数相关,为O(n),getrange和字符串长度相关,也是O(n),其余的命令基本上都是O(1)的时间复杂度,在速度上还是非常快的。

使用场景

字符串类型的使用场景很广泛:

缓存功能

Redis 作为缓存层,MySQL作为存储层,绝大部分请求的数据都是从Redis中获取。由于Redis具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用。

计数

使用Redis 作为计数的基础工具,它可以实现快速计数、查询缓存的功能,同时数据可以异步落地到其他数据源。

共享Session

一个分布式Web服务将用户的Session信息(例如用户登录信息)保存在各自服务器中,这样会造成一个问题,出于负载均衡的考虑,分布式服务会将用户的访问均衡到不同服务器上,用户刷新一次访问可能会发现需要重新登录,这个问题是用户无法容忍的。

为了解决这个问题,可以使用Redis将用户的Session进行集中管理,,在这种模式下只要保证Redis是高可用和扩展性的,每次用户更新或者查询登录信息都直接从Redis中集中获取。

限速

比如,很多应用出于安全的考虑,会在每次进行登录时,让用户输入手机验证码,从而确定是否是用户本人。但是为了短信接口不被频繁访问,会限制用户每分钟获取验证码的频率,例如一分钟不能超过5次。一些网站限制一个IP地址不能在一秒钟之内方问超过n次也可以采用类似的思路。

哈希(Hash)

Java里提供了HashMap,Redis中也有类似的数据结构,就是哈希类型。但是要注意,哈希类型中的映射关系叫作field-value,注意这里的value是指field对应的值,不是键对应的值。

操作命令

基本上,哈希的操作命令和字符串的操作命令很类似,很多命令在字符串类型的命令前面加上了h字母,代表是操作哈希类型,同时还要指明要操作的field的值。

hset设值

hset user:1 name lijin

image.png

如果设置成功会返回1,反之会返回0。此外Redis提供了hsetnx命令,它们的关系就像set和setnx命令一样,只不过作用域由键变为field。

hget取值

hget user:1 name

如果键或field不存在,会返回nil。

image.png

hdel删除field

hdel会删除一个或多个field,返回结果为成功删除field的个数。

image.png

hlen计算field个数

image.png

hmset批量设值

image.png

hmget批量取值

image.png

hexists判断field是否存在

image.png

若存在返回1,不存在返回0

hkeys获取所有field

它返回指定哈希键所有的field

image.png

hvals获取所有value

image.png

hgetall获取所有field与value

image.png

在使用hgetall时,如果哈希元素个数比较多,会存在阻塞Redis的可能。如果只需要获取部分field,可以使用hmget,如果一定要获取全部field-value,可以使用hscan命令,该命令会渐进式遍历哈希类型,hscan将在后面的章节介绍。

hincrby增加

hincrby和 hincrbyfloat,就像incrby和incrbyfloat命令一样,但是它们的作用域是filed。

hstrlen 计算value的字符串长度

image.png

命令的时间复杂度

哈希类型的操作命令中,hdel,hmget,hmset的时间复杂度和命令所带的field的个数相关O(k),hkeys,hgetall,hvals和存储的field的总数相关,O(N)。其余的命令时间复杂度都是O(1)。

使用场景

从前面的操作可以看出,String和Hash的操作非常类似,那为什么要弄一个hash出来存储。

哈希类型比较适宜存放对象类型的数据,我们可以比较下,如果数据库中表记录user为:

idnameage
1lijin18
2msb20

1、使用String类型

需要一条条去插入获取。

set user:1:name lijin;

set user:1:age 18;

set user:2:name msb;

set user:2:age 20;

优点:简单直观,每个键对应一个值

缺点:键数过多,占用内存多,用户信息过于分散,不用于生产环境

2、将对象序列化存入redis

set user:1 serialize(userInfo);

优点:编程简单,若使用序列化合理内存使用率高

缺点:序列化与反序列化有一定开销,更新属性时需要把userInfo全取出来进行反序列化,更新后再序列化到redis

3、使用hash类型

hmset user:1 name lijin age 18

hmset user:2 name msb age 20

优点:简单直观,使用合理可减少内存空间消耗

缺点:要控制内部编码格式,不恰当的格式会消耗更多内存

列表(list)

列表( list)类型是用来存储多个有序的字符串,a、b、c、c、b四个元素从左到右组成了一个有序的列表,列表中的每个字符串称为元素(element),一个列表最多可以存储(2^32-1)个元素(4294967295)。

image.png

在Redis 中,可以对列表两端插入( push)和弹出(pop),还可以获取指定范围的元素列表、获取指定索引下标的元素等。列表是一种比较灵活的数据结构,它可以充当栈和队列的角色,在实际开发上有很多应用场景。

列表类型有两个特点:

第一、列表中的元素是有序的,这就意味着可以通过索引下标获取某个元素或者某个范围内的元素列表。

第二、列表中的元素可以是重复的。

操作命令
lrange 获取指定范围内的元素列表(不会删除元素)

key start end

索引下标特点:从左到右为0到N-1

lrange 0 -1命令可以从左到右获取列表的所有元素

rpush 向右插入

image.png

image.png

lpush 向左插入

image.png

image.png

linsert 在某个元素前或后插入新元素

image.png

image.png

image.png

这三个返回结果为命令完成后当前列表的长度,也就是列表中包含的元素个数,同时rpush和lpush都支持同时插入多个元素。

lpop 从列表左侧弹出(会删除元素)

image.pngr

请注意,弹出来元素就没了。

rpop 从列表右侧弹出

rpop将会把列表最右侧的元素d弹出。

image.png

lrem 对指定元素进行删除

image.png

lrem命令会从列表中找到等于value的元素进行删除,根据count的不同分为三种情况:

count>0,从左到右,删除最多count个元素。

count<0,从右到左,删除最多count绝对值个元素。

count=0,删除所有。

image.png

image.png

image.png

image.png

返回值是实际删除元素的个数。

ltirm 按照索引范围修剪列表

例如想保留列表中第0个到第1个元素

image.pngls

lset修改指定索引下标的元素

image.png

lindex 获取列表指定索引下标的元素

image.pngl

llen 获取列表长度

image.png

blpop和brpop阻塞式弹出元素

blpop和brpop是lpop和rpop的阻塞版本,除此之外还支持多个列表类型,也支持设定阻塞时间,单位秒,如果阻塞时间为0,表示一直阻塞下去。我们以brpop为例说明。

image.png

A客户端阻塞了(因为没有元素就会阻塞)

image.png

A客户端一直处于阻塞状态。此时我们从另一个客户端B执行

image.png

A客户端则输出

image.png

注意:brpop后面如果是多个键,那么brpop会从左至右遍历键,一旦有一个键能弹出元素,客户端立即返回。

使用场景

列表类型可以用于比如:

消息队列,Redis 的 lpush+brpop命令组合即可实现阻塞队列,生产者客户端使用lrpush从列表左侧插入元素,多个消费者客户端使用brpop命令阻塞式的“抢”列表尾部的元素,多个客户端保证了消费的负载均衡和高可用性。

文章列表

每个用户有属于自己的文章列表,现需要分页展示文章列表。此时可以考虑使用列表,因为列表不但是有序的,同时支持按照索引范围获取元素。

实现其他数据结构

lpush+lpop =Stack(栈)

lpush +rpop =Queue(队列)

lpsh+ ltrim =Capped Collection(有限集合)

lpush+brpop=Message Queue(消息队列)


http://www.ppmy.cn/devtools/166989.html

相关文章

JVM垃圾收集器合集

前言&#xff1a;JVM GC收集器的回顾与比较 JVM&#xff08;Java虚拟机&#xff09;中的垃圾收集器是自动管理内存的重要机制&#xff0c;旨在回收不再使用的对象所占用的内存空间。以下是JVM中几种常见的垃圾收集器的详细介绍&#xff1a; 一、新生代垃圾收集器 1.Serial收集…

【Crypto】CTF 密码学题目解题思路图

CTF密码学题目解题思路图 密码学题目 ├── 1. 编码/转换 │ ├── 1.1 Base64 │ │ └── 步骤&#xff1a;检查填充字符&#xff08;&#xff09;&#xff0c;解码工具&#xff08;CyberChef&#xff09;。 │ ├── 1.2 Hex │ │ └── 步骤&#xff1a…

C++蓝桥杯基础篇(十一)

片头 嗨~小伙伴们&#xff0c;大家好&#xff01;今天我们来学习C蓝桥杯基础篇&#xff08;十一&#xff09;&#xff0c;学习类&#xff0c;结构体&#xff0c;指针相关知识&#xff0c;准备好了吗&#xff1f;咱们开始咯~ 一、类与结构体 类的定义&#xff1a;在C中&#x…

打造流畅的下拉刷新与轮播交互:HarmonyOS手势识别与组件协同实战

打造流畅的下拉刷新与轮播交互&#xff1a;HarmonyOS手势识别与组件协同实战 在现代移动应用开发中&#xff0c;流畅且自然的交互体验是提升用户满意度的关键因素之一。下拉刷新和轮播组件是许多应用中常见的功能&#xff0c;但如何让它们在手势操作中无缝协同工作&#xff0c…

智能三防手持终端破解传统仓储效率困局

在数字化浪潮的推动下&#xff0c;传统仓储管理模式正面临效率低、成本高、错误频发等瓶颈。如何实现精准、高效、智能化的仓储管理&#xff0c;上海岳冉三防智能手持终端机以RFID技术为核心&#xff0c;结合工业级三防&#xff08;防水、防摔、防尘&#xff09;设计&#xff0…

内检实验室lims系统在电子设备制造行业的应用

在电子设备制造行业&#xff0c;内检实验室LIMS&#xff08;实验室信息管理系统&#xff09;的应用正变得日益重要。随着技术的不断进步和行业标准的提高&#xff0c;传统的手工记录和管理方式已难以满足现代电子制造业的需求。LIMS系统通过整合多种功能和技术&#xff0c;为电…

2019年蓝桥杯第十届CC++大学B组真题及代码

目录 1A&#xff1a;组队&#xff08;填空5分_手算&#xff09; 2B&#xff1a;年号字符&#xff08;填空5分_进制&#xff09; 3C&#xff1a;数列求值&#xff08;填空10分_枚举&#xff09; 4D&#xff1a;数的分解&#xff08;填空10分&#xff09; 5E&#xff1a;迷宫…

React Next项目中导入Echart世界航线图

公司业务要求做世界航线图&#xff0c;跑了三个ai未果&#xff0c;主要是引入world.json失败&#xff0c;echart包中并不携带该文件&#xff0c;源码的world.json文件页面404找不到。需要自己寻找。这是整个问题卡壳的关键点&#xff0c;特此贴出资源网址。 一、安装 npm inst…