文章目录
- string基本认识
- 重谈set
- 重谈get
- mset和mget
- setnx/setex/psetex
- incr系列命令
- 字符串其他操作
- string的编码方式
- string的应用场景
- 缓存功能
- session会话
- 手机验证码
本篇开始总结的是Redis中的string类型
string基本认识
Redis中的string来说,所有的key都是字符串,但是对于Value的类型来说是有区别的,对于Redis的数据存储来说,存储的是什么,那么拿出来的就是什么,例如存储的是某种格式的数据,那么不会出现存取不一致的情况
而对于Redis的Value来说,不仅仅可以存储文本数据,还可以存储的是整数,普通的文本字符串,JSON,xml等等,还可以存储有例如二进制数据,例如有图片,视频,音频等
但是并不建议使用Redis存储过大的内容,因为Redis本身是一个单线程的模型,如果使用了过大的加载会导致整体上的操作变慢,甚至出现阻塞的情况,这是不被建议和允许的
重谈set
前面对于set命令其实并不到位,原因在于只是使用了一个最基本的功能,下面演示一种另外的功能:
SET key value [expiration EX seconds|PX milliseconds] [NX|XX]
下面先介绍一下最后的两个选项:
- 如果选择的是NX,表示的是,如果key值不存在,再设置,如果key值存在,就不设置,同时返回nill
- 如果选择的是XX,表示的是,如果key存在,才设置,相当于更新key的value,如果key不存在,就不设置,返回nil
对于Redis的标准文档给出的语法格式的说明有:
[]
表示的是一个独立的单元,这个单元可以存在也可以不存在,而在这当中如果有|
的存在,表示的是或者的意思,换句话说是只能出现一个,但是[]
和|
是可以同时出现的
因此下面我们给出一个事例:
set key value ex 10
对于这个语句来说,它表示有两个意思:
set key value
expire key 10
重谈get
对于get来说,它只是支持可以获得对应的value值,但是如果是其他类型的value值会获取出错
正常的场景:
127.0.0.1:6379> set key1 1
OK
127.0.0.1:6379> set key2 2
OK
127.0.0.1:6379> set key3 3
OK
127.0.0.1:6379> get key1
"1"
但是如果使用一个链表进行设置:
127.0.0.1:6379> lpush key4 a b c d
(integer) 4
127.0.0.1:6379> get key4
(error) WRONGTYPE Operation against a key holding the wrong kind of value
此时再获取,就会显示获取失败,由此可以看出,对于get方法来说,如果value并非是string类型,那么此时获取就会失败,这里只支持获取的是string类型
mset和mget
上述讲述的设置键值对的get方法,只是针对于获取一个信息,但是在网络的传输过程中涉及到了很多的封装和分用的过程,所以最好我们建议是能够一次传输很多的数据,这样可以避免频繁的进行网络的封装和分用的过程,具体原理如下所示:
我们推荐是使用第二种方式进行传输的,因此下面就介绍的是mset和mget命令
127.0.0.1:6379> mset key1 1 key2 2 key3 3 key4 4
OK
127.0.0.1:6379> keys *
1) "key1"
2) "key4"
3) "key3"
4) "key2"
127.0.0.1:6379> mget key1 key2 key3
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> mget key4 key5
1) "4"
2) (nil)
正常来说,Redis保证这个操作的时间复杂度是O(N),其中N是key的数量,但是不可否认的是,如果这个N到达一定程度,例如如果到达的数量是10w个键值对,那么这也是一件不可接受的事,因为这就意味着此时会把Redis有很大的几率阻塞,Redis是单线程模型,因此这是严重的错误,因此即使使用这个命令,也要注意使用的量
setnx/setex/psetex
下面的这一组命令,说的是set的一些缩写
set有很多的用法,针对于一些常用的用法都进行了缩写,例如上述的这三种命令
- setnx表示的是,不存在才能设置,如果存在就设置失败
- setex和psetex表示的是,设置的是key的过期时间,单位分别是秒和毫秒
incr系列命令
下面介绍的是incr系列的命令
- incr:针对于整数进行value+1的命令
- incrby:针对于整数进行value+n的命令
- decr:针对于整数进行value-1的命令
- decrby:针对于整数进行value-n的命令
- incrbyfloat:针对于value进行+或者-一个小数
具体使用事例如下:
127.0.0.1:6379> keys *
1) "key1"
2) "key4"
3) "key3"
4) "key2"
127.0.0.1:6379> get key1
"1"
127.0.0.1:6379> incr key1
(integer) 2
127.0.0.1:6379> get key1
"2"
127.0.0.1:6379> incr keyy
(integer) 1
127.0.0.1:6379> get keyy
"1"
值得注意的是,当incr的是一个0的时候,表示的是把一个内容当做0,并把它加上对应的值
上述的时间复杂度全部都是O(1),并且这时候就体现出Redis单线程的好处:由于Redis是单线程的模型,所以针对于多个客户端同时对一个key进行的incr的操作,并不会引起线程安全的问题
字符串其他操作
Redis的string类型还支持有一些关于字符串的经典操作,例如有拼接,获取,修改字符串的部分内容,获取字符串的长度等等
append/setrange/strlen
append的返回值长度是字节,在Redis中的字符串,是不会对于字符的编码进行任何处理的,Redis只会识别到字符,不会识别到字节的存在,因此当目前的shell终端的编码方式是utf8,那么在shell进行输入的汉字后,也会按照utf8进行编码,而一个汉字在utf8的字符集中,通常是占据的是3个字节
所以如果想要让Redis显示出对应的汉字,就可以在进行启动客户端的时候带上有–raw这样的选项,这样的选项就代表着想要让Redis尝试进行把二进制数据翻译的效果,下面演示这种场景
127.0.0.1:6379> set key1 学习
OK
127.0.0.1:6379> get key1
"\xe5\xad\xa6\xe4\xb9\xa0"
getrange
这个函数相当于是在C++中的substr函数,相当于是一个字符串切分的函数,并且值得注意的是,对于这个函数来说,在Redis中演示的效果是一个两个都是闭区间,而在C++中,谈及的区间大多都是左闭右开的区间,但是不得不说也有特殊情况,例如Redis就是这样的情况
不仅如此,Redis中甚至允许下标是负数的存在
setrange
这个函数相当于是进行一个范围内字符串的替换,函数的返回值是替换后新的字符串的长度
string的编码方式
在string的内部存在三种编码方式:
- int:64位的正数
- embstr:压缩字符串,适合与表示比较短的字符串
- raw:普通字符串,适用于表示比较长的字符串,只是单纯的持有字节数组
string的应用场景
缓存功能
如上所示,是应用服务器结合Redis使用的一种场景,对于整体的思路上来说,在应用服务器进行访问数据的时候,首先会查询Redis,当查询到具体的数据后,就会直接从Redis上把数据读取下来,而不再会访问数据库
而如果Redis上的数据不存在,那么就要去到MySQL中进行数据的读取,再把读取到的数据返回给应用服务器,不再继续访问数据库了,同时,如果是从MySQL中进行读取,那么也会把读取到的数据缓存到Redis中
Redis作为缓存,经常会用来存储一些热点数据,而带来的问题是,随着时间的推移,一定会导致Redis中的数据越来越多,那么对应的就会出现存储空间不足的问题,对应的也有解决措施:
- 把数据写给Redis的同时,给这个key设置一个过期时间,超过这个时间就会自动过期
- Redis也会在内存不足的时候,提供一个淘汰策略
session会话
这个问题也并不陌生,这里用一张图来进行说明
手机验证码
第三种场景是手机验证码的场景,这里展示其中的一些逻辑
- 生成验证码
- 检查验证码
具体的逻辑在后续会进行演示