【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.mzph.cn/bicheng/27410.shtml

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

相关文章

『大模型笔记』主成分分析(PCA)解释:简化机器学习中的复杂数据!

主成分分析(PCA)解释:简化机器学习中的复杂数据 文章目录 一. 主成分分析(PCA)解释:简化机器学习中的复杂数据!二. 参考文献一. 主成分分析(PCA)解释:简化机器学习中的复杂数据! 主成分分析(Principal Component Analysis,简称PCA)通过 将大型数据集中的维度减少…

C#开发-集合使用和技巧(二)Lambda 表达式介绍和应用

C#开发-集合使用和技巧 Lambda 表达式介绍和应用 C#开发-集合使用和技巧介绍简单的示例&#xff1a;集合查询示例&#xff1a; 1. 基本语法从主体语句上区分&#xff1a;1. 主体为单一表达式2. 主体是代码块&#xff08;多个表达式语句&#xff09; 从参数上区分1. 带输入参数的…

【数据结构初阶】 --- 单链表

关于链表你应该先了解这些 下图描述了物理模型和逻辑模型&#xff0c;大多数常见的其实是逻辑模型&#xff0c;但这对初学者或者掌握不扎实的同学不太友好&#xff0c;所以这里我重点讲解物理模型&#xff0c;当了解了这些细节&#xff0c;以后做题或是什么就直接画逻辑模型就…

Java优雅统计耗时【工具类】

任务耗时如何优雅的打印&#xff0c;看完本文你就明白了&#xff01;~ import cn.hutool.core.date.StopWatch; import cn.hutool.core.lang.Console;/*** 优雅打印出任务耗时*/ public class Main {public static void main(String[] args) throws Exception{StopWatch stopW…

macOS Sequoia 开发者测试版下载和安装教程

macOS Sequoia 于 2024年6月10日在WWDC 2024 上发布&#xff0c;里面添加了AI、窗口排列、操控iPhone等功能&#xff0c;目前发布的为测试版本&#xff0c;可能很多人不知道怎么去下载安装&#xff0c;现在小编教一下大家怎么安装最新的 macOS Sequoia 开发者测试版。 下载 mac…

2024 年最新使用 Node 搭建QQ开放平台官方 QQ 频道机器人详细教程(更新中)

注册 QQ 开放平台账号 QQ 开放平台是腾讯应用综合开放类平台&#xff0c;包含 QQ 机器人、QQ 小程序、QQ 小游戏 等集成化管理&#xff0c;也就是说你注册了QQ 开放平台&#xff0c;你开发 QQ 机器人还是 QQ 小程序都是在这个平台进行部署上线和管理。 如何注册 QQ 开放平台账…

JAVAEE值之网络原理(1)_用户数据报协议(UDP)、概念、特点、结构、代码实例

前言 在前两节中我们介绍了UDP数据报套接字编程&#xff0c;但是并没有对UDP进行详细介绍&#xff0c;本节中我们将会详细介绍传输层中的UDP协议。 一、什么是UDP&#xff1f; UDP工作在传输层&#xff0c;用于程序之间传输数据的。数据一般包含&#xff1a;文件类型&#xff0…

超图制作栅格数据集专题图示例

之前写过一两篇专题图的博文&#xff0c;是制作的矢量数据集的专题图&#xff1b; 有一个栅格数据集如下&#xff0c;不知是干嘛的&#xff0c;可能是一个地形&#xff0c;或水系&#xff1b; 看一下对栅格数据集制作专题图&#xff1b;能制作的专题图类型少些&#xff0c; 先…

R 文件优化插件:Binary XML file in layout Error inflating class

场景一&#xff1a;构造函数缺失 问题 自定义布局&#xff08;FlagmentLayout&#xff09;加载自定义属性失败&#xff0c;导致广告显示异常&#xff0c;甚至是闪退&#xff5e; InflateException 在 Android 中我们遇到的通常发生在自定义 View 创建中&#xff0c;动态加载…

探索交互设计:五大关键维度全面剖析

交互式设计是用户体验&#xff08;UX&#xff09;设计的重要组成部分。在本文中&#xff0c;我将向大家解释什么是交互设计并简要描述交互设计师通常每天都做什么。 一、什么是交互设计 交互式设计用简单的术语来理解就是用户和产品之间的交互。在大多数情况下&#xff0c;当…

大白菜PE系统进入时一直 ACPI_BIOS_ERROR

安装系统PE不支持&#xff0c;主板不兼容&#xff0c;换个WIN10的PE就解决了&#xff0c;跟之前部分电脑需要WIN8的PE同理 WIN10PE教程 WIN8PE教程

CLIPSeg

作者回答问题敷衍&#xff0c;不建议复现

谷歌Google广告开户要提供什么材料?

谷歌Google广告是企业出海&#xff0c;触及全球潜在客户的必备渠道&#xff0c;无论您是初创公司还是成熟企业&#xff0c;想要在激烈的市场竞争中脱颖而出&#xff0c;有效利用谷歌广告的力量至关重要。云衔科技&#xff0c;作为数字化营销解决方案与SaaS软件服务商&#xff0…

【Tkinter界面】Canvas 图形绘制(02/5)

文章目录 一、说明二、几何时使用 Canvas 组件2.1 用法2.2 简单范例2.3 对象移动2.4 对象删除2.5 文字对象显示 三、画布和画布对象3.1 画布生成函数原型3.2 使用create_xxx()方法3.3 对参数**options的解释 一、说明 Canvas&#xff08;画布&#xff09;组件为 Tkinter 的图形…

多类型图像OCR:基于Dify的多模态Agent实现

大模型相关目录 大模型&#xff0c;包括部署微调prompt/Agent应用开发、知识库增强、数据库增强、知识图谱增强、自然语言处理、多模态等大模型应用开发内容 从0起步&#xff0c;扬帆起航。 大模型应用向开发路径&#xff1a;AI代理工作流大模型应用开发实用开源项目汇总大模…

记录一下PHP使用微信小程序支付

记录一下PHP使用微信小程序支付V3版本经历 官方文档&#xff1a;https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_0.shtml 请详细查看文档中小程序支付接入前准备&#xff08;https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_8_1.shtml&#xff…

仿element-ui 实现自己组件库 <3>

目录 input 组件封装 v-model用在组件上 显示和隐藏密码 封装switch组件 实现转换的功能 设置checkbox input 组件封装 首先input组件的基本框架和样式&#xff1a; <div class"miao-input"><input class"miao-input_inner" > </div…

网络编程(四)

一、使用wireshark抓包分析协议头 &#xff08;一&#xff09;wireshark常用的过滤语句 tcp.port <想要查看的端口号> ip.src <想要查看的源IP地址> ip.dest <想要查看的目的IP地址> ip.addr <想要查看的IP地址>&#xff08;二&#xff09;抓包分…

Burp Suite Professional 2024.5 (macOS, Linux, Windows) - Web 应用安全、测试和扫描

Burp Suite Professional 2024.5 (macOS, Linux, Windows) - Web 应用安全、测试和扫描 Burp Suite Professional, Test, find, and exploit vulnerabilities. 请访问原文链接&#xff1a;Burp Suite Professional 2024.5 (macOS, Linux, Windows) - Web 应用安全、测试和扫描…

IP服务器代理如何设置使用?

IP服务器代理&#xff08;通常称为代理IP或代理服务器&#xff09;的设置和使用方法可以根据不同的需求和场景而有所不同。以下是一个清晰的步骤指南&#xff0c;帮助你设置和使用IP服务器代理&#xff1a; 1. 选择合适的代理IP类型 根据使用目的的不同&#xff0c;可以选择不…