【redis 】string类型详解

string类型详解

一、string类型的概念

字符串类型是 Redis 最基础的数据类型,关于字符串需要特别注意:

  1. ⾸先 Redis 中所有的键的类型都是字符串类型,⽽且其他⼏种数据结构也都是在字符串类似基础上构建的,例如列表和集合的元素类型是字符串类型,所以字符串类型能为其他 4 种数据结构的学习奠定基础。
  1. 如上图所⽰,字符串类型的值实际可以是字符串,包含⼀般格式的字符串或者类似 JSON、XML 格式的字符串;数字,可以是整型或者浮点型;甚⾄是⼆进制流数据,例如图⽚、⾳频、视频等。不过⼀个字符串的最⼤值不能超过 512 MB。

二、string类型的常用指令

2.1 SET

将 string 类型的 value 设置到 key 中。如果 key 之前存在,则覆盖,⽆论原来的数据类型是什么。之前关于此 key 的 TTL(键值对的过期时间) 也全部失效。

语法:

r 复制代码
SET key value [EX seconds|PX milliseconds|KEEPTTL] [NX|XX]

\]内是选填项,其他的是必填项 * EX seconds:以秒作为单位设置key的过期时间 * PX milliseconds:以毫秒作为单位设置key的过期时间 * KEEPTTL:保留设置前指定键的生存时间 * NX:只在key不存在时才设置,如果设置前key已存在,则不执行 * XX:只在key存在时才设置,如果设置前key不存在,则不执行 返回值:成功返回ok,失败返回nil 使用方法: * 当创建的value值没有空格时:可加引号可不加引号没有影响 * 当创建的value值有空格时需要加引号,否则会报错 ```r //不存在时创建 127.0.0.1:6379> set key nexit nx OK 127.0.0.1:6379> get key "nexit" //存在不创建 127.0.0.1:6379> set key look nx (nil) //存在时创建 127.0.0.1:6379> set key exit xx OK 127.0.0.1:6379> get key "exit" //不存在不创建 127.0.0.1:6379> set key1 look xx (nil) //设置key的过期时间为10秒 127.0.0.1:6379> set key second ex 10 OK 127.0.0.1:6379> get key "second" //十秒后key被销毁 127.0.0.1:6379> get key (nil) ``` #### 2.2 GET 获取 key 对应的 value。如果 key 不存在,返回 nil。如果 value 的数据类型不是 string,会报错。 语法: ```r GET key ``` 返回值:key 对应的 value,或者 nil 当 key 不存在时 使用方法: ```r 127.0.0.1:6379> set key hello OK 127.0.0.1:6379> get key "hello" //没创建key2,找不到 127.0.0.1:6379> get key2 (nil) //key3不是string类型,报错 127.0.0.1:6379> hset key3 name lx (integer) 1 127.0.0.1:6379> get key3 (error) WRONGTYPE Operation against a key holding the wrong kind of value ``` #### 2.3 MSET ⼀次性设置多个 key 的值 ```r MSET key value [key value ...] ``` 返回值:永远是 OK 使用方法: ```r 127.0.0.1:6379> mset key1 'name' key2 'age' OK 127.0.0.1:6379> get key1 "name" 127.0.0.1:6379> get key2 "age" ``` #### 2.4 MGET ⼀次性获取多个 key 的值。如果对应的 key 不存在或者对应的数据类型不是 string,返回 nil 语法: ```r MGET key [key ...] ``` 返回值:对应 value 的列表 使用方法: ```r 127.0.0.1:6379> mset key1 'hello' key2 'world' key3 'redis' OK 127.0.0.1:6379> mget key1 key2 key3 1) "hello" 2) "world" 3) "redis" ``` 多次get 和单次mget的区别: 多次get会客户端会和服务器进行多次网络通信 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/074a204cc0d247fda1c1324c7f3115c6.png) 单次mget客户端和服务器只进行一次网络通信 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/34addfda8ee84311a6619d1379134841.png) 使⽤ mget / mset 由于可以有效地减少了⽹络时间,所以性能相较更⾼。假设⽹络耗时 1 毫秒,命令执⾏时间耗时 0.1 毫秒,则执⾏时间如表 所⽰ 1000 次 get 和 1 次 mget 对⽐ | 操作 | 时间 | |:----------------:|:-------------------------------:| | 1000 次 get | 1000 x 1 + 1000 x 0.1 = 1100 毫秒 | | 1 次 mget 1000 个键 | 1 x 1 + 1000 x 0.1 = 101 毫秒 | 学会使⽤批量操作,可以有效提⾼业务处理效率,但是要注意,每次批量操作所发送的键的数量也不是⽆节制的,否则可能造成单⼀命令执⾏时间过⻓,导致 Redis 阻塞 #### 2.5 SETNX 设置 key-value 但只允许在 key 之前不存在的情况下 语法: ```r SETNX key value ``` 返回值:1 表⽰设置成功。0 表⽰没有设置 使用方法: ```r 127.0.0.1:6379> setnx key 'hello' (integer) 1 127.0.0.1:6379> setnx key 'nihao' (integer) 0 127.0.0.1:6379> get key "hello" ``` SET、SET NX 和 SET XX 的执⾏流程如图 : ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/947030cbb1554f499a416be951e9bf42.png) #### 2.6 INCR 将 key 对应的 string 表⽰的数字加⼀。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错 语法: ```r INCR key ``` 返回值:integer 类型的加完后的数值 使用方法: ```r //key 不存在,0 + 1 = 1 127.0.0.1:6379> exists key (integer) 0 127.0.0.1:6379> incr key (integer) 1 //整数类型,可以直接加1 127.0.0.1:6379> set key '20' OK 127.0.0.1:6379> incr key (integer) 21 //超出了整数类型,报错 127.0.0.1:6379> set key '234293482390480948029348230948' OK 127.0.0.1:6379> incr key (error) ERR value is not an integer or out of range //不是整数类型,报错 127.0.0.1:6379> set key 'not a number' OK 127.0.0.1:6379> incr key (error) ERR value is not an integer or out of range ``` #### 2.7 INCRBY 将 key 对应的 string 表⽰的数字加上对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错 语法: ```r INCRBY key decrement ``` 返回值:integer 类型的加完后的数值 使用方法: ```r //key 不存在,0 + 1 = 1 127.0.0.1:6379> exists key (integer) 0 127.0.0.1:6379> incrby key 3 (integer) 3 //整数类型,可以直接加3 127.0.0.1:6379> set key '10' OK 127.0.0.1:6379> incrby key 3 (integer) 13 //不能使用非整数类型来加,报错 127.0.0.1:6379> incrby key 'not a number' (error) ERR value is not an integer or out of range //所加以后的值超出整数类型,报错 127.0.0.1:6379> incrby key '234293482390480948029348230948' (error) ERR value is not an integer or out of range //不能对非整数类型相加 127.0.0.1:6379> set key 'not a number' OK 127.0.0.1:6379> incrby key 3 (error) ERR value is not an integer or out of range ``` #### 2.8 DECR 将 key 对应的 string 表⽰的数字减⼀。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错 语法: ```r DECR key ``` 返回值:integer 类型的减完后的数值 使用方法: ```r //对整数相减 127.0.0.1:6379> exists key (integer) 0 127.0.0.1:6379> decr key (integer) -1 127.0.0.1:6379> set key '10' OK 127.0.0.1:6379> decr key (integer) 9 //超出整数范围,报错 127.0.0.1:6379> set key '234293482390480948029348230948' OK 127.0.0.1:6379> decr key (error) ERR value is not an integer or out of range //不是整数类型,报错 127.0.0.1:6379> set key 'not a number' OK 127.0.0.1:6379> decr key (error) ERR value is not an integer or out of range ``` #### 2.9 DECRBY 将 key 对应的 string 表⽰的数字减去对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的 string 不是⼀个整型或者范围超过了 64 位有符号整型,则报错。 语法: ```r DECRBY key decrement ``` 返回值:integer 类型的减完后的数值 使用方法: ```r //对整数类型直接相减 127.0.0.1:6379> exists key (integer) 0 127.0.0.1:6379> decrby key 3 (integer) -3 127.0.0.1:6379> set key '10' OK 127.0.0.1:6379> decrby key 3 (integer) 7 //不能使用非整数类型来减 127.0.0.1:6379> decrby key 'not a number' (error) ERR value is not an integer or out of range //超出了整数类型,报错 127.0.0.1:6379> set key '234293482390480948029348230948' OK 127.0.0.1:6379> decrby key (error) ERR wrong number of arguments for 'decrby' command //对非整数类型相减,报错 127.0.0.1:6379> set key 'not a number' OK 127.0.0.1:6379> decrby key 3 (error) ERR value is not an integer or out of range ``` #### 2.10 INCRBYFLOAT 将 key 对应的 string 表⽰的浮点数加上对应的值。如果对应的值是负数,则视为减去对应的值。如果 key 不存在,则视为 key 对应的 value 是 0。如果 key 对应的不是 string,或者不是⼀个浮点数,则报错。允许采⽤科学计数法表⽰浮点数。 语法: ```r INCRBYFLOAT key increment ``` 返回值:加/减完后的数值 使用方法: ```r //正数时,相加 127.0.0.1:6379> set key 10.10 OK 127.0.0.1:6379> incrbyfloat key 0.1 "10.2" 负数时,相减 127.0.0.1:6379> incrbyfloat key -6 "4.2" 127.0.0.1:6379> set key 6.0e3 OK 127.0.0.1:6379> incrbyfloat key 2.0e3 "8000" ``` 很多存储系统和编程语⾔内部使⽤ CAS 机制实现计数功能,会有⼀定的 CPU 开销,但在 Redis 中完全不存在这个问题,因为 Redis 是单线程架构,任何命令到了 Redis 服务端都要顺序执⾏ #### 2.11 APPEND 语法: ```r APPEND KEY VALUE ``` 返回值:追加完成之后 string 的⻓度 使用方法: ```r 127.0.0.1:6379> get key (nil) 127.0.0.1:6379> append key 'hello' (integer) 5 127.0.0.1:6379> get key "hello" 127.0.0.1:6379> append key 'world' (integer) 10 127.0.0.1:6379> get key "helloworld" ``` #### 2.12 GETRANGE 返回 key 对应的 string 的⼦串,由 start 和 end 确定(左闭右闭)。可以使⽤负数表⽰倒数。-1 代表倒数第⼀个字符,-2 代表倒数第⼆个,其他的与此类似。超过范围的偏移量会根据 string 的⻓度调整成正确的值。 语法: ```r GETRANGE key start end ``` 返回值:string 类型的⼦串 使用方法: ```r 127.0.0.1:6379> set key 'this is a string' OK 127.0.0.1:6379> getrange key 0 3 "this" 127.0.0.1:6379> getrange key -3 -1 "ing" 127.0.0.1:6379> getrange key 0 -1 "this is a string" ``` #### 2.13 SETRANGE 覆盖字符串的⼀部分,从指定的偏移开始 语法: ```r SETRANGE key offset value ``` 返回值:替换后的 string 的⻓度 使用方法: ```r 127.0.0.1:6379> set key 'hello world' OK 127.0.0.1:6379> setrange key 6 'redis' (integer) 11 127.0.0.1:6379> get key "hello redis" //如果key不存在,从零位置开始替换不会报错 127.0.0.1:6379> setrange key1 0 'hello' (integer) 5 127.0.0.1:6379> get key1 "hello" //key不存在,从0以后的位置开始会报错 127.0.0.1:6379> set range key2 3 'hello' (error) ERR syntax error ``` #### 2.14 STRLEN 获取 key 对应的 string 的⻓度。当 key 存放的类似不是 string 时,报错 语法: ```r STRLEN key ``` 返回值:string 的⻓度。或者当 key 不存在时,返回 0 使用方法: ```r 127.0.0.1:6379> set key 'hello world' OK 127.0.0.1:6379> strlen key (integer) 11 127.0.0.1:6379> strlen nonexisting (integer) 0 ``` ### 三、string类型的命令小结 | 命令 | 执⾏效果 | 时间复杂度 | |----------------------------------|------------------------------|--------------------------| | set key value \[key value...\] | 设置 key 的值是 value | O(k), k 是键个数 | | get key | 获取 key 的值 | O(1) | | del key \[key ...\] | 删除指定的 key | O(k), k 是键个数 | | mset key value \[key value ...\] | 批量设置指定的 key 和 value | O(k), k 是键个数 | | mget key \[key ...\] | 批量获取 key 的值 | O(k), k 是键个数 | | incr key | 指定的 key 的值 +1 | O(1) | | decr key | 指定的 key 的值 -1 | O(1) | | incrby key n | 指定的 key 的值 +n | O(1) | | decrby key n | 指定的 key 的值 -n | O(1) | | incrbyfloat key n | 指定的 key 的值 +n | O(1) | | append key value | 指定的 key 的值追加 value | O(1) | | strlen key | 获取指定 key 的值的⻓度 | O(1) | | setrange key offset value | 覆盖指定 key 的从 offset 开始的部分值 | O(n),n 是字符串⻓度, 通常视为 O(1) | | getrange key start end | 获取指定 key 的从 start 到 end 的部分值 | O(n),n 是字符串⻓度, 通常视为 O(1) | ### 四、string类型的内部编码 字符串类型的内部编码有 3 种: 1. int:8 个字节的⻓整型。 2. embstr:⼩于等于 39 个字节的字符串 3. raw:⼤于 39 个字节的字符串 Redis 会根据当前值的类型和⻓度动态决定使⽤哪种内部编码实现 整型类型⽰例如下: ```r 127.0.0.1:6379> set key 6379 OK 127.0.0.1:6379> object encoding key "int" ``` 短字符串⽰例如下: ```r //⼩于等于 39 个字节的字符串 127.0.0.1:6379> set key "hello" OK 127.0.0.1:6379> object encoding key "embstr" ``` ⻓字符串⽰例如下: ```r //⼤于 39 个字节的字符串 127.0.0.1:6379> set key "one string greater than 39 bytes ........" OK 127.0.0.1:6379> object encoding key "raw" ``` ### 五、string类型的典型使用场景 缓存(Cache)功能 * 下图 是⽐较典型的缓存使⽤场景,其中 Redis 作为缓冲层,MySQL 作为存储层,绝⼤部分请求的数据都是从 Redis 中获取。由于 Redis 具有⽀撑⾼并发的特性,所以缓存通常能起到加速读写和降低后端压⼒的作⽤ 计数(Counter)功能 * 许多应⽤都会使⽤ Redis 作为计数的基础⼯具,它可以实现快速计数、查询缓存的功能,同时数据可以异步处理或者落地到其他数据源。例如视频⽹站的视频播放次数可以使⽤ Redis 来完成:⽤⼾每播放⼀次视频,相应的视频播放数就会⾃增 1 共享会话(Session) * ⼀个分布式 Web 服务将⽤⼾的 Session 信息(例如⽤⼾登录信息)保存在各⾃的服务器中,但这样会造成⼀个问题:出于负载均衡的考虑,分布式服务会将⽤⼾的访问请求均衡到不同的服务器上,并且通常⽆法保证⽤⼾每次请求都会被均衡到同⼀台服务器上,这样当⽤⼾刷新⼀次访问是可能会发现需要重新登录,这个问题是⽤⼾⽆法容忍的 ⼿机验证码 * 很多应⽤出于安全考虑,会在每次进⾏登录时,让⽤⼾输⼊⼿机号并且配合给⼿机发送验证码,然后让⽤⼾再次输⼊收到的验证码并进⾏验证,从⽽确定是否是⽤⼾本⼈。为了短信接⼝不会频繁访问,会限制⽤⼾每分钟获取验证码的频率,例如⼀分钟不能超过 5 次 以上介绍了使⽤ Redis 的字符串数据类型可以使⽤的⼏个场景,但其适⽤场景远不⽌于此 。

相关推荐
光军oi18 分钟前
Mysql从入门到精通day5————子查询精讲
android·数据库·mysql
天上掉下来个程小白20 分钟前
Redis-12.在Java中操作Redis-Spring Data Redis使用方式-操作字符串类型的数据
java·redis·spring·springboot·苍穹外卖
qr9j422332 小时前
Django自带的Admin后台中如何获取当前登录用户
数据库·django·sqlite
cherry52302 小时前
【PostgreSQL】【第4章】PostgreSQL的事务
数据库·postgresql
Amd7945 小时前
FastAPI中Pydantic异步分布式唯一性校验
redis·fastapi·分布式锁·多级缓存·pydantic·唯一性校验·异步校验
IT成长日记6 小时前
【MySQL基础】聚合函数从基础使用到高级分组过滤
数据库·mysql·聚合函数
Guarding and trust7 小时前
python系统之综合案例:用python打造智能诗词生成助手
服务器·数据库·python
夜间出没的AGUI8 小时前
SQLiteBrowser 的详细说明,内容结构清晰,涵盖核心功能、使用场景及实用技巧
数据库
J不A秃V头A8 小时前
Redis批量操作详解
开发语言·redis