【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 的字符串数据类型可以使⽤的⼏个场景,但其适⽤场景远不⽌于此 。

相关推荐
不光头强3 小时前
Spring框架的事务管理
数据库·spring·oracle
百***92025 小时前
【MySQL】MySQL库的操作
android·数据库·mysql
q***76665 小时前
Spring Boot 从 2.7.x 升级到 3.3注意事项
数据库·hive·spring boot
信仰_2739932435 小时前
Redis红锁
数据库·redis·缓存
人间打气筒(Ada)5 小时前
Centos7 搭建hadoop2.7.2、hbase伪分布式集群
数据库·分布式·hbase
心灵宝贝5 小时前
如何在 Mac 上安装 MySQL 8.0.20.dmg(从下载到使用全流程)
数据库·mysql·macos
奋斗的牛马6 小时前
OFDM理解
网络·数据库·单片机·嵌入式硬件·fpga开发·信息与通信
忧郁的橙子.7 小时前
一、Rabbit MQ 初级
服务器·网络·数据库
杰杰7987 小时前
SQL 实战:用户访问 → 下单 → 支付全流程转化率分析
数据库·sql
爬山算法7 小时前
Redis(120)Redis的常见错误如何处理?
数据库·redis·缓存