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

news2024/11/22 16:26:07

本文将详细介绍 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) {
         响应 404
         return 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 次发送限制,限制发送,返回 null
            return 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.coloradmin.cn/o/1827274.html

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

相关文章

使用消息队列(MQ)实现MySQL持久化存储与MySQL server has gone away问题解决

在现代应用程序开发中&#xff0c;消息队列&#xff08;MQ&#xff09;扮演着重要的角色。它们可以帮助我们解决异步通信和解耦系统组件之间的依赖关系。而其中一个常见的需求是将消息队列中的数据持久化到数据库中&#xff0c;以确保数据的安全性和可靠性。在本文中&#xff0…

gbase8s数据库阻塞检查点和非阻塞检查点的执行机制

1. 检查点的描述 为了便于数据库系统的复原和逻辑恢复&#xff0c;数据库服务器生成的一致性标志点&#xff0c;称为检查点&#xff0c;其是建立在数据库系统的已知和一致状态时日志中的某个时间点检查点的目的在于定期将逻辑日志中的重新启动点向前移动 如果存在检查点&#…

【Quartus 13.0】NIOS II 部署UART 和 PWM

打算在 EP1C3T144I7 芯片上部署 nios ii 做 uart & pwm控制 这个芯片或许不够做 QT 部署 这个芯片好老啊&#xff0c;但是做控制足够了&#xff0c;我只是想装13写 leader给的接口代码是用VHDL写的&#xff0c;我不会 当然verilog我也不太会 就这样&#xff0c;随便写吧 co…

[大模型]XVERSE-7B-chat Transformers 推理

XVERSE-7B-Chat为XVERSE-7B模型对齐后的版本。 XVERSE-7B 是由深圳元象科技自主研发的支持多语言的大语言模型&#xff08;Large Language Model&#xff09;&#xff0c;参数规模为 70 亿&#xff0c;主要特点如下&#xff1a; 模型结构&#xff1a;XVERSE-7B 使用主流 Deco…

【ARMv8/ARMv9 硬件加速系列 3.2 -- SVE 读写内存指令 st1b | st1w | st1w | st1d 使用介绍】

文章目录 SVE Load 和 Store 指令使用介绍LD1 加载指令ST1 存储指令PFR 预取指令参考示例LD1 加载示例ST1 存储示例 代码实例 SVE Load 和 Store 指令使用介绍 ARMv9架构中的SVE&#xff08;Scalable Vector Extension&#xff09;指令集为向量计算提供了强大支持&#xff0c;…

fs.1.10 ON rockeylinux8 dockerfile模式

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 rockeylinux8 docker上编译安装fs.1.10的流程记录&#xff0c;本文使用dockerfile模式。 环境 docker engine&#xff1a;Version 24.0.6 rockylinux docker&#xff1a;8 freeswitch&#xff1a;v1.10.7 dockerfi…

CleanMyMacX4.15.4如何优化苹果电脑系统缓存,告别MacBook卡顿,提升mac电脑性能

你是否曾为苹果电脑存储空间不够而烦恼&#xff1f;是否曾因系统运行缓慢而苦恼&#xff1f;别担心&#xff0c;今天我要给大家种草一个神器——CleanMyMac&#xff01;这款软件可以帮助你轻松解决苹果电脑的种种问题&#xff0c;让你的电脑焕然一新&#xff01; 让我来给大家介…

显著提高iOS应用中Web页面的加载速度 - 提前下载页面的关键资源(如JavaScript、CSS和图像)

手动下载并缓存资源是一种有效的方式&#xff0c;可以确保在需要时资源已经在本地存储&#xff0c;这样可以显著提高加载速度。 缓存整个 web 页面的所有资源文件 具体实现步骤 下载和缓存资源&#xff1a;包括 HTML 文件、CSS、JavaScript 和图像。在应用启动时预加载资源。…

CSS从入门到精通——动画:CSS3动画执行次数和逆向播放

目录 任务描述 相关知识 动画执行次数 动画反向播放 编程要求 任务描述 本关任务&#xff1a;用 CSS3 实现loading效果。效果图如下&#xff1a; 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.动画执行次数&#xff0c;2.动画反向播放。 需要实现的效…

CSS从入门到精通——动画:CSS3动画延迟和完成后状态的保持

目录 任务描述 相关知识 动画状态 动画完成时的状态 动画延迟 编程要求 任务描述 本关任务&#xff1a;用 CSS3 实现小车等待红绿灯的效果。效果图如下&#xff1a; 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.动画状态&#xff0c;2.动画完成时的状…

mac下Xcode在iphone真机上测试运行iOS软件

最近一个需求需要在iPhone真机上测试一个视频直播的项目。 需要解决如何将项目 app 安装到真机上 在进行真机调试。 安装Xcode 直接在App Store上搜索Xcode安装即可。 关键是要安装Simulator。项目需要安装iOS17.5但是由于安装包太大&#xff0c;并且网络不稳定的原因。在Xco…

关于yolov5训练的那些事儿

1.YOLOv5 的模型系列包括从最小到最大的多种模型&#xff1a;YOLOv5n&#xff08;Nano&#xff09;&#xff0c;YOLOv5s&#xff08;Small&#xff09;&#xff0c;YOLOv5m&#xff08;Medium&#xff09;&#xff0c;YOLOv5l&#xff08;Large&#xff09;&#xff0c;以及 YO…

【Linux硬盘读取】Windows下读取Linux系统的文件解决方案:Linux Reader4.5 By DiskInternals

前言 相信做机器视觉相关的很多人都会安装 Windows 和 Linux 双系统。在 Linux 下&#xff0c;我们可以很方便的访问Windows的磁盘&#xff0c;反过来却不行。但是这又是必须的。通过亲身体验&#xff0c;向大家推荐这么一个工具&#xff0c;可以让 Windows 方便的访问 Ext 2/3…

Linux 文件的权限信息解读 chmod修改权限 数字序号表示权限

ls -l #列出当前文件 显示详细信息 drwxr-xr-x. 2 dpc test 6 Jun 15 07:45 test.txt共分为三部分 drwxr-xr-x.&#xff1a;表示文件和文件夹的权限信息dpc &#xff1a;文件&#xff0c;文件夹所属的用户test &#xff1a; 文件和文件夹所属的用户组 drwxr-xr-x 解读 d表示为…

实用软件下载:BetterZip 5最新安装包及详细安装教程

BetterZip是一款功能强大的Mac解/压缩软件&#xff0c;可以满足用户对文件压缩、解压、加密和保护等方面的需求。以下是关于BetterZip软件的主要功能、特点和使用方法的详细介绍&#xff0c;以及对其用户友好度、稳定性和安全性的评价。 安 装 包 获 取 地 址: BetterZip 5-安…

【尚庭公寓SpringBoot + Vue 项目实战】公寓管理(十一)

【尚庭公寓SpringBoot Vue 项目实战】公寓管理&#xff08;十一&#xff09; 文章目录 【尚庭公寓SpringBoot Vue 项目实战】公寓管理&#xff08;十一&#xff09;1、业务介绍2、逻辑模型介绍3、接口开发3.1、保存或更新公寓信息3.2、根据条件分页查询详细信息3.3、根据ID获…

深度学习(七)——神经网络的卷积操作

卷积操作 一、torch.nn中Convolution Layers函数的介绍 1. 参数介绍 nn.Conv1d: Conv取自Convolution的前四个字母&#xff0c;1d代表的是一个一维操作。 nn.Conv2d: 2d表示是一个二维的操作&#xff0c;比如图像就是一个二维的。 其余参数不常用&#xff0c;见官网文档&am…

分布式事务AP控制方案(下)

分布式事务控制方案 本篇文章给出一种要求高可用性&#xff08;AP思想&#xff09;的分布式事务控制方案 上篇回顾&#xff1a;点我查看 分布式事务控制方案1、前景回顾2、数据库和缓存的操作3、分布式文件系统1&#xff09;页面静态化2&#xff09;远程调用3&#xff09;调用…

adb卸载系统应用

1.进入shell adb shell2.查看所有包 pm list packages3.查找包 如查找vivo相关的包 pm list packages | grep vivo发现包太多了,根本不知道哪个是我们想卸载的应用 于是可以打开某应用,再查看当前运行应用的包名 如下: 4.查找当前前台运行的包名 打开某应用,在亮屏状态输入 …

卫星通讯助力船舶可视化监控:EasyCVR视频汇聚系统新应用

一、背景 随着科技的不断进步和社会治安的日益严峻&#xff0c;视频监控系统已经成为维护公共安全和提升管理效率的重要工具。传统的视频监控主要依赖于有线传输&#xff0c;但受到地域限制、布线成本高等因素的影响&#xff0c;其应用范围和效果受到一定限制。而卫星通讯传输…