【Redis】String的常用命令及图解String使用场景

本文将详细介绍 Redis String 类型的常见命令及其使用场景,包括缓存、计数器、共享会话、手机验证码、分布式锁等场景,并且配图和伪代码进一步方便理解和使用。

命令执行效果时间复杂度
set key value [key value…]设置key的值是valueO(k),k是键个数
get key获取key的值O(1)
del key [key …]删除指定的keyO(k),k是键个数
mset key value [key value …]批量设置指定的key和valueO(k),k是键个数
mget key [key …]批量获取key的值O(k),k是键个数
incr key指定的key的值+1O(1)
decr key指定的key的值-1O(1)
incrby key n定的key的值+nO(1)
decrby key n指定的key的值-nO(1)
incrbyfloat key n指定的key的值+nO(1)
append key value指定的key的值追加valueO(1)
strlen key获取指定key的值的长度O(1)

setrange key offset value

覆盖指定key的从offset开始的部分值

O(n),n是字符串长度,通常视为0(1)

getrange key start end

获取指定key的从start到end的部分值

O(n),n是字符串长度,通常视为O(1)

 1. 相关命令演示

# SET 命令
# 设置 key1 的值为 "Hello"
# 时间复杂度: O(1)
127.0.0.1:6379> SET key1 "Hello"
OK# 设置 key2 的值为 "Redis"
# 时间复杂度: O(1)
127.0.0.1:6379> SET key2 "Redis"
OK# GET 命令
# 获取 key1 的值
# 时间复杂度: O(1)
127.0.0.1:6379> GET key1
"Hello"# DEL 命令
# 删除 key1
# 时间复杂度: O(1) 对单个键
127.0.0.1:6379> DEL key1
(integer) 1# 尝试获取已经被删除的 key1 的值
# 时间复杂度: O(1)
127.0.0.1:6379> GET key1
(nil)# MSET 命令
# 批量设置多个键值对
# 时间复杂度: O(k), k 是键的个数
127.0.0.1:6379> MSET key1 "Hello" key2 "Redis" key3 "!"
OK# MGET 命令
# 批量获取多个键的值
# 时间复杂度: O(k), k 是键的个数
127.0.0.1:6379> MGET key1 key2 key3
1) "Hello"
2) "Redis"
3) "!"# INCR 命令
# 将 counter 的值加 1
# 时间复杂度: O(1)
127.0.0.1:6379> SET counter 10
OK
127.0.0.1:6379> INCR counter
(integer) 11# DECR 命令
# 将 counter 的值减 1
# 时间复杂度: O(1)
127.0.0.1:6379> DECR counter
(integer) 10# INCRBY 命令
# 将 counter 的值加 5
# 时间复杂度: O(1)
127.0.0.1:6379> INCRBY counter 5
(integer) 15# DECRBY 命令
# 将 counter 的值减 3
# 时间复杂度: O(1)
127.0.0.1:6379> DECRBY counter 3
(integer) 12# INCRBYFLOAT 命令
# 将 counter 的值加 2.5(浮点数)
# 时间复杂度: O(1)
127.0.0.1:6379> INCRBYFLOAT counter 2.5
"14.5"# APPEND 命令
# 将 " World" 追加到 key1 的值后
# 时间复杂度: O(1)
127.0.0.1:6379> APPEND key1 " World"
(integer) 11
127.0.0.1:6379> GET key1
"Hello World"# STRLEN 命令
# 获取 key1 的值的长度
# 时间复杂度: O(1)
127.0.0.1:6379> STRLEN key1
(integer) 11# SETRANGE 命令
# 从偏移量 6 开始,将 key1 的值替换为 "Redis"
# 时间复杂度: O(n),n 是字符串的长度,通常视为 O(1)
127.0.0.1:6379> SET key1 "Hello World"
OK
127.0.0.1:6379> SETRANGE key1 6 "Redis"
(integer) 11
127.0.0.1:6379> GET key1
"Hello Redis"# GETRANGE 命令
# 获取 key1 从偏移量 0 到 4 的部分值
# 时间复杂度: O(n),n 是字符串的长度,通常视为 O(1)
127.0.0.1:6379> GETRANGE key1 0 4
"Hello"

2. 内部编码

Redis 中的字符串(String)类型是最基本的数据类型。为了高效地存储和操作字符串数据,Redis对字符串类型进行了多种内部编码优化。具体来说,字符串的内部编码主要有以下三种:intembstrraw。

int:8 个字节的⻓整型。
embstr:⼩于等于 39 个字节的字符串。 【Redis 3.2 及之前版本
raw:⼤于 39 个字节的字符串。 【Redis 3.2 及之前版本

Redis 4.0 及之后版本

  • embstr 编码:用于长度小于等于 44 字节的字符串。
  • raw 编码:用于长度大于 44 字节的字符串。

2.1 int

当一个字符串的值可以表示为 64 位(8字节)带符号整数时,Redis 会将该字符串编码为 int 类型。这种编码方式节省了内存,并且可以更高效地执行诸如 INCRDECR 等操作。

127.0.0.1:6379> SET myint 100
OK
127.0.0.1:6379> OBJECT ENCODING myint
"int"

2.2. embstr

当字符串的长度小于等于 44 字节时,Redis 会使用 embstr 编码。这种编码将 Redis 对象和实际字符串数据存储在连续的内存块中,因此在内存分配和访问上更加高效。embstr 编码在创建时效率很高,但一旦需要修改字符串内容,它会转换为 raw 编码。

127.0.0.1:6379> SET shortstr "Hello, Redis!"
OK
127.0.0.1:6379> OBJECT ENCODING shortstr
"embstr"

2.3 raw

当字符串长度大于 44 字节或需要进行修改操作时,Redis 会使用 raw 编码。raw 编码将 Redis 对象和字符串数据分开存储。这种方式适用于较长字符串或频繁修改的字符串,因为在这种情况下,内存分配和管理会更加高效。

127.0.0.1:6379> SET longstr "This is a very long string that exceeds the embstr limit."
OK
127.0.0.1:6379> OBJECT ENCODING longstr
"raw"

来看一下我使用的版本

 验证一下是39字节还是44字节发生内部编码类型的变化

测试长度为 39 字节的字符串

 测试长度为 44 字节的字符串

测试长度为 45 字节的字符串

 3 典型使用场景

3.1 缓存(Cache)功能

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

 下面的伪代码模拟了图 2-10 的业务数据访问过程

1. 假设业务是根据用户 uid 获取用户信息

UserInfo getUserInfo(long uid) {...
}

2. 首先从 Redis 获取用户信息,我们假设用户信息保存在"user:info:<uid>" 对应的键中

1 // 根据 uid 得到 Redis 的键
2 String key = "user:info:" + uid;
3
4 // 尝试从 Redis 中获取对应的值
5 String value = Redis 执行命令:get key;
7 // 如果缓存命中(hit)
8 if(value != null){
9     //假设我们的用户信息按照 JSON 格式存储
10    UserInfo userInfo = JSON 反序列化(value);
11    return userInfo:
12 }

3. 如果没有从 Redis 中得到用户信息,及缓存 miss,则进一步从 MVSOL中获取对应的信息,随后写入缓存并返回:

// 如果缓存未命中(miss)
if (value == null) {// 从数据库中,根据 uid 获取⽤⼾信息UserInfo userInfo = MySQL 执⾏ SQL:select * from user_info where uid = <uid>// 如果表中没有 uid 对应的⽤⼾信息if (userInfo == null) {响应 404return null;}// 将⽤⼾信息序列化成 JSON 格式String value = JSON 序列化(userInfo);// 写⼊缓存,为了防⽌数据腐烂(rot),设置过期时间为 1 ⼩时(3600 秒)Redis 执⾏命令:set key value ex 3600// 返回⽤⼾信息return userInfo;
}

3.2 计数器功能

许多应用都会使用 Redis 作为计数的基础工具,它可以实现快速计数、查询缓存的功能,同时数据可以异步处理或者落地到其他数据源。如下图所示,例如视频网站的视频播放次数可以使用Redis 来完成:用户每播放一次视频,相应的视频播放数就会自增 1

 3.3 共享会话

如图所示,一个分布式Web 服务将用户的 Session 信息(例如用户登录信息)保存在各自的服务器中,但这样会造成一个问题:出于负载均衡的考虑,分布式服务会将用户的访问请求均衡到不同的服务器上,并且通常无法保证用户每次请求都会被均衡到同一台服务器上,这样当用户刷新一次访问是可能会发现需要重新登录,这个问题是用户无法容忍的。

为了解决这个问题,可以使用 Redis 将用户的 Session 信息进行集中管理,如下图所示,在这种模式下,只要保证 Redis 是高可用和可扩展性的,无论用户被均衡到哪台 Web 服务器上,都集中从Redis 中查询、更新 Session 信息。

3.4 手机验证码

很多应用出于安全考虑,会在每次进行登录时,让用户输入手机号并且配合给手机发送验证码,然后让用户再次输入收到的验证码并进行验证,从而确定是否是用户本人。为了短信接口不会频繁访会限制用户每分钟获取验证码的频率,例如一分钟不能超过5次,如图所示。

 此功能可以⽤以下伪代码说明基本实现思路

// 发送验证码并处理发送频率限制
String 发送验证码(String phoneNumber) {// 构造用于限制短信发送频率的 Redis 键String key = "shortMsg:limit:" + phoneNumber;// 尝试在 Redis 中设置键值对,设置过期时间为 1 分钟(60 秒),只在键不存在时才能成功(NX 参数)boolean r = Redis.执行命令:set key 1 ex 60 nx;if (!r) {// 如果设置失败,说明之前已经设置过该手机号的发送频率限制// 增加计数器,表示又发送了一次验证码long c = Redis.执行命令:incr key;if (c > 5) {// 如果超过了一分钟内的 5 次发送限制,限制发送,返回 nullreturn null;}}// 生成随机的 6 位数验证码String validationCode = 生成随机的 6 位数的验证码();// 设置验证码的存储键,有效期设置为 5 分钟(300 秒)String validationKey = "validation:" + phoneNumber;Redis.执行命令:set validationKey validationCode ex 300;// 返回生成的验证码,后续通过手机短信发送给用户return validationCode;
}// 验证用户输入的验证码是否正确
boolean 验证验证码(String phoneNumber, String validationCode) {// 构造存储验证码的 Redis 键String validationKey = "validation:" + phoneNumber;// 从 Redis 中获取存储的验证码值String value = Redis.执行命令:get validationKey;if (value == null) {// 如果没有找到该手机号的验证码记录,验证失败return false;}// 比较用户输入的验证码是否和存储的验证码一致,返回相应的验证结果return value.equals(validationCode);
}

3.5 分布式锁

在 Redis 中,String 类型可以用于实现简单的分布式锁:

  • 原子性操作: Redis 的命令是原子性的,即 Redis 单个命令的执行是不可中断的,要么全部执行成功,要么全部不执行,不存在部分执行的情况。例如,SETNX 命令(设置值并仅在键不存在时设置成功)和 DEL 命令(删除键值对)都是原子操作。这种特性确保了在高并发环境下,对分布式锁的获取和释放操作是可靠的。

  • 并发控制Redis 是单线程的,通过事件循环和非阻塞 I/O 实现高并发处理。虽然 Redis 本身是单线程的,但其内部使用了时间片轮转机制来实现多个客户端的请求处理。这使得 Redis 能够高效处理大量的并发请求,适合作为分布式锁的存储和管理工具。

  • 过期时间可以为 Redis 的 String 类型设置过期时间(Expiration),即在设置键值对时可以指定键的生存时间。这一特性对于分布式锁尤为重要,可以避免因为客户端异常退出而造成的死锁情况。设置合适的过期时间可以确保即使锁未显式释放,也能在一定时间后自动释放,从而避免资源长时间被锁定。

 此功能可以⽤以下伪代码说明基本实现思路

// 示例中的参数
String lockKey = "resource_lock";
String clientId = UUID.randomUUID().toString();// 执行 SETNX 命令
boolean lockAcquired = Redis.执行命令:setnx(lockKey, clientId);if (lockAcquired) {// 如果成功获得锁try {// TODO: 执行业务逻辑} finally {// 释放锁Redis.执行命令:del(lockKey);}
} else {// 获取锁失败的处理逻辑// TODO: 处理获取锁失败的情况
}

命令说明

  • 当执行 SETNX lockKey clientId 命令时,Redis 将尝试设置键 lockKey 的值为 clientId
  • 如果 lockKey 已经存在(即已被其他客户端设置),SETNX 命令将会设置失败,返回 0
  • 如果 lockKey 不存在,SETNX 命令将设置成功,返回 1 表示获取了锁。

注意事项

  • 获取锁后,一定要确保最终释放锁,以避免锁被长时间持有而造成资源无法访问。
  • 可以结合设置过期时间的方式来实现自动释放锁,避免因客户端异常退出而导致的死锁问题。

以上介绍了使用Redis的字符串数据类型可以使用的几个场景,但其适用场景远不止于此,开发人员可以结合字符串类型的特点以及提供的命令,充分发挥自己的想象力,在自己的业务中去找到合适的场景去使用Redis的字符串类型。


码字不易,如果有用还请三连支持哦。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

长难句打卡6.14

When public opinion is particularly polarized, as it was following the end of the Franco regime, monarchs can rise above “mere” politics and “embody” a spirit of national unity. 当公众舆论严重分化时&#xff0c;正如佛朗哥执政未期那样&#xff0c;君主们就…

Vulnhub-DC-9

靶机IP:192.168.20.144 kaliIP:192.168.20.128 网络有问题的可以看下搭建Vulnhub靶机网络问题(获取不到IP) 信息收集 nmap扫描一下端口及版本号 dirsearch扫目录 最后去前端界面观察发现也没什么隐藏路径。 观察功能&#xff0c;search引起注意&#xff0c;SQL注入测试 当输…

AI论文速读 | 2024[SIGIR]基于大语言模型的下一个兴趣点推荐

论文标题&#xff1a;Large Language Models for Next Point-of-Interest Recommendation 作者&#xff1a;Peibo Li ; Maarten de Rijke ; Hao Xue &#xff08;薛昊&#xff09;; Shuang Ao ; Yang Song ; Flora D. Salim 机构&#xff1a;新南威尔士大学(UNSW)&#xff0c…

Uni-App中的u-datetime-picker时间选择器Demo

目录 前言Demo 前言 对于网页端的推荐阅读&#xff1a;【ElementUI】详细分析DatePicker 日期选择器 事情起因是两个时间选择器同步了&#xff0c;本身是从后端慢慢步入全栈&#xff0c;对此将这个知识点从实战进行提炼 通过Demo进行总结 Demo 用于选择日期和时间的组件&a…

【TB作品】MSP430G2553,DS1302,LCD1602,时间读取和显示,万年历,Proteus仿真

效果 部分代码 #include <MSP430.h> #include "ds1302.h" #include "LCD.h"//关掉ccs优化&#xff0c;并且Convert_BCD_To_Dec函数中只能是10.0f才行&#xff0c;不然有bugvoid main(void) {char cnt 0;char disp[16];WDTCTL WDTPW WDTHOLD; /* …

基于springboot实现农产品直卖平台系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现农产品直卖平台系统的设计演示 摘要 计算机网络发展到现在已经好几十年了&#xff0c;在理论上面已经有了很丰富的基础&#xff0c;并且在现实生活中也到处都在使用&#xff0c;可以说&#xff0c;经过几十年的发展&#xff0c;互联网技术已经把地域信息的隔…

错题记录(小测)

单选 错题1 错题2 错题3 代码题 反转链表 链表的回文结构

linux系统宝塔服务器temp文件夹里总是被上传病毒php脚本

目录 简介 上传过程 修复上传漏洞 tmp文件夹总是被上传病毒文件如下图: 简介 服务器时不时的会发送短信说你服务器有病毒, 找到了这个tmp文件, 删除了之后又有了。 确实是有很多人就这么无聊, 每天都攻击你的服务器。 找了很久的原因, 网上也提供了一大堆方法,…

万字长文爆肝Spring(一)

Spring_day01 今日目标 掌握Spring相关概念完成IOC/DI的入门案例编写掌握IOC的相关配置与使用掌握DI的相关配置与使用 1&#xff0c;课程介绍 对于一门新技术&#xff0c;我们需要从为什么要学、学什么以及怎么学这三个方向入手来学习。那对于Spring来说: 1.1 为什么要学? …

Star-CCM+自动网格执行方法与设置技巧

在Star中进行一个仿真项目时,有时会创建多个自动网格。网格创建结束后需要执行。在Star中,网格执行可以分为三种。分别是:单独执行操作;多个执行操作;全部执行操作。接下来将三种执行操作的方法与步骤进行介绍。 其次,如果不习惯用自定义控制网格,有时在一个项目中就会…

如何应对pcdn的流量攻击?

面对PCDN的流量攻击&#xff0c;可以采取以下措施来应对&#xff1a; 一&#xff0e;配置防火墙&#xff1a; 1.禁止未授权的PCDN域名访问&#xff1a;根据网络需求&#xff0c;配置防火墙规则&#xff0c;只允许特定的PCDN域名进行访问&#xff0c;从而防止未经授权的PCDN节…

53.Python-web框架-Django开始第一个应用的多语言

针对上一篇的功能&#xff0c;本次仅对页面做了多语言&#xff0c;大家可以看看效果。 51.Python-web框架-Django开始第一个应用的增删改查-CSDN博客 目录 部门列表 新增部门 编辑部门 部门列表 源码 <!DOCTYPE html> {% load static %} {% load i18n %} <html …

如何在 Windows 10/11 上编辑 PDF [4 种简单方法]

PDF 在大多数设备上都易于查看&#xff0c;但由于其设计用于查看&#xff0c;因此编辑起来可能比较棘手。编辑 PDF 可能比编辑 Microsoft Office 文档更具挑战性。 不用担心&#xff0c;我们已经为你做好了准备。无论你是想添加、删除还是插入文本或图片&#xff0c;你都可以使…

深入理解并打败C语言难关之一————指针(4)

前言&#xff1a; 我们在前面的几讲中已经讲了指针的很多内容了&#xff0c;现在我们开始层层递进&#xff0c;要探寻更多的指针喽&#xff0c;不多废话了&#xff0c;直接进入正题&#xff0c;开始今天的指针之旅喽&#xff01; 目录&#xff1a; 1.字符指针变量 1.1常量字符…

英语学习笔记36——Where ... ?

Where … ? ……在哪里&#xff1f; 词汇 Vocabulary beside prep. 在……旁边 同义词&#xff1a; near by 构成&#xff1a;be side side n. 边 搭配&#xff1a;side walk 人行道 例句&#xff1a;Bobby在我旁边。    Bobby is beside me. off prep. 离开&#xff…

《站在2024年的十字路口:计算机专业是否仍是高考生的明智之选?》

文章目录 每日一句正能量前言行业竞争现状行业饱和度和竞争激烈程度[^3^]新兴技术的影响[^3^]人才需求的变化[^3^]行业创新动态如何保持竞争力 专业与个人的匹配度判断专业所需的技术能力专业核心课程对学生的要求个人兴趣和性格特点专业对口的职业发展要求实践和经验个人价值观…

高考志愿填报选专业,兴趣爱好和就业前景哪个优先?

每个人都有自己的兴趣与爱好&#xff0c;而高考志愿填报是在为自己选择职业方向。最理想的状态就是把自己的兴趣和爱好与自己的职业统一起来&#xff0c;让兴趣和爱好促进职业的发展&#xff0c;为职业增添动力。但现实生活中&#xff0c;这种理想的状态并不是每个人都能达到的…

探索未来边界:前沿技术引领新纪元

目录 引言 一、人工智能与深度学习&#xff1a;智慧生活的引擎 1.医疗应用 2.智能家居 3.自动驾驶 二、量子计算&#xff1a;解锁宇宙的密钥 1.量子比特示意图 2.量子计算机实物图 3.分子模拟应用 三、生物技术&#xff1a;生命科学的革新 1.CRISPR-Cas9基因编辑图 2.合成生…

Python 学习 用Python第二册 第9章内容解八皇后问题

----用教授的方法学习 目录 1.八皇后问题 2.状态表示(抽象) 3.检测冲突 4.基线条件 5.递归条件 6.结尾 1.八皇后问题 深受大家喜爱的计算机科学谜题&#xff1a;你需要将8个皇后放在棋盘上&#xff0c;条件是任何一个皇后都不能威胁其他皇后&#xff0c;即任何两个皇后…

灾备建设中虚拟机细粒度恢复的含义及技术使用

灾备建设中为了考虑虚拟机恢复的效率与实际的用途&#xff0c;在恢复上出了普通的恢复虚拟机&#xff0c;也有其余的恢复功能&#xff0c;比如瞬时恢复&#xff0c;细粒度恢复等。这里谈的就是细粒度恢复。 首先细粒度恢复是什么&#xff0c;这个恢复可以恢复单个备份下来的文…