Redis
中的字符串,直接就是按照二进制数据方式进行存储的!(不会进行任何的编码转换,存的是啥,取出来的就是啥)。Redis
对于string
类型,限制了大小最大是512M
。redis
单线程模型,希望进行的操作都能比较迅速。
可以存储文本数据,整数、普通字符串、JSON、XML、二进制数据(图片,视频、音频)
append
APPEND KEY VALUE:字符串追加字符串
127.0.0.1:6379> set key1 "123"
OK
127.0.0.1:6379> append key1 你好
(integer) 9
127.0.0.1:6379> get key1
"123\xe4\xbd\xa0\xe5\xa5\xbd"
xshell
中断,默认字符编码都是UTF-8
,在中断中输入汉字之后,也是按照UTF8
编码的,一个汉字在UTF-8
字符集中,通常是3
个字符。
getrange
功能:返回key
对应的闭区间[start, end]
的value
字符串。start和end也可以为负数-1
GETRANGE key range start end
127.0.0.1:6379> set key hwlloworld
OK
127.0.0.1:6379> getrange key 0 -1
"hwlloworld"
127.0.0.1:6379> getrange key 1 -2
"wlloworl"
127.0.0.1:6379> set key1 你好
OK
127.0.0.1:6379> getrange key1 0 -1
"\xe4\xbd\xa0\xe5\xa5\xbd"
127.0.0.1:6379> getrange key1 0 -2
"\xe4\xbd\xa0\xe5\xa5"
setrange
功能:覆盖字符串的一部分,从指定的偏移开始。z
注意:插入中文会导致乱码!
SETRANGE key offset value
127.0.0.1:6379> set key helloworld
OK
127.0.0.1:6379> setrange key 1 aaa
(integer) 10
127.0.0.1:6379> get key
"haaaoworld"
当我们向不存在的key中加字符串时,会凭空生成一个0x00字节。将value插到这个0x00后面了。
127.0.0.1:6379> setrange key2 1 aaa
(integer) 4
127.0.0.1:6379> get key2
"\x00aaa"
strlen
获取key对应的string的长度。当key存放的类似不是string时,报错。
时间复杂度:$O(1)$
STRLEN key
127.0.0.1:6379> set key "hello world!"
OK
127.0.0.1:6379> strlen key
(integer) 12
字符串类型的内部编码有3中:
127.0.0.1:6379> object encoding key
"int"
127.0.0.1:6379> set key2 hello
OK
127.0.0.1:6379> object encoding key2
"embstr"
127.0.0.1:6379> set key3 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
OK
127.0.0.1:6379> object encoding key3
"raw"
对于某个业务场景,有很多很多的key,类型都是string,但是每个value的string长度都是100左右。字符串使用embstr来存储也不是不能考虑。
上述效果具体怎么实现?
Redis会根据当前值的类型和长度动态决定存储值的类型。
127.0.0.1:6379> set key4 1.4
OK
127.0.0.1:6379> object encoding key4
"embstr"
redis存储小数,本质上还是当做字符串来存储,这就和整数相比差别就很大了。小数都是使用字符串来存,意味着每次进行算术运算,都需要把字符串转换为小数,进行运算,结果再转回字符串来保存。
图中是比较典型的缓存实用场景,其中Redis
作为缓冲层,MySQL
作为存储层,绝大部分请求都是从Redis
中获取。由于Redis
具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用。
{: height=75%, width=75%}
整体思路:
应用服务器访问数据的时候,先查询Redis
。
Redis
上的数据存在了,就直接从Redis
取数据交给应用服务器。Redis
上数据不存在,在读取MySQL
。把读到的结果,返回给应用服务器。同时,把这个数据页写入到Redis
中。上述策略存在一个明显的问题:
随着时间的推移,肯定会有越来越多的key
在redis
上访问不到。从而从MySQL
读取并写入Redis
了。此时redis
中数据就会越来越多。
redis
的同时,给key
设置一个过期时间。Redis
也存在内存不足的时候,提供了淘汰策略。很多应用都会使用Redis
作为技术工具的计数工具,它可以实现快速计数、查询缓存的功能,同时数据可以异步处理货值落地到其他数据元源。例如视频网站播放次数可以使用Redis
完成:用户每播放一次视频,相应的视频播放就会自增1
。
{: height=75%, width=75%}
一个分布式Web服务器将用户的Session信息(例如用户的登录信息)保存在各自的服务器中,但这样会造成一个问题:出于负载均衡的考虑,分布式服务会将用户的访问请求均衡到不同的服务器上,并且通常无法保证用户每次请求都会被均衡到同一台服务器上,这样当用户刷新一次访问可能发现需要重新登录,这个问题是用户无法容忍的。
我们可以使用redis,把所有的会话统一放到redis里面。任何服务器要想访问seesion就要先访问seesion。
很多应用出于安全考虑,会在每次登录时,让用户输入手机号并且配合给手机发送验证码,然后让用户再次输入收到的验证码并进行验证,从而确定是否是用户本人。为了短信接口不会频繁访问,会限制用户每分钟获取验证码的频率:例如一分钟不能成功5次。
命令 | 执行效果 | 时间复杂度 |
---|---|---|
set key value | 设置key的值 | O(1) |
del key [key...] | 删除指定的key | O(k) |
meset key value [key value...] | 批量设置指定的key和value | O(k) |
mget key [key...] | 批量获取key的值 | O(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) |
getrange key start end | 获取指定key的从start到end的部分值 | O(n) |