常规操作
1、键值对
支持增删改操作
> set name zj
OK
> get name
"zj"
> exists name
(integer) 1
> del name
(integer) 1
> get name
(nil)
2、批量键值对
可以对多个字符串进行批量读写,节省网络耗时开销。
> mset name1 zj1 name2 zj2 name3 zj3
> mget name1 name2 name3 name
1) "zj1"
2) "zj2"
3) "zj3"
4) (nil)
3、过期和set命令扩展
可以为key设置过期时间,设置方式为以下两种方式
方式一:
> set name zj
> get name
"zj"
> expire name 10
... #等待10s
> get name
(nil)
方式二:
> setex name 10 zj
> get name
"zj"
... #等待10s
> get name
(nil)
4、计数
当字符串是一个整数时,可以进行自增操作,但是必须是在整数的取值范围内(超出时回报错)。
> set year 2019
OK
> incr year
(integer) 2020
> incrby year 10
(integer) 2030
> incrby year -10
(integer) 2020
5、其他
如何判断一个key是否存在,且存在不改变,不存在赋值
> setnx key1 jj
(integer) 1
> get key1
"jj"
> setnx key1 zj
(integer) 0
> get key1
"jj"
内部实现
Redis中的字符串是可以修改的字符串,在内存中它是以字节数组的形式存在的。
内部结构
Redis 的字符串的结构为SDS(Simple Dynamic String 简单动态字符串)。其具体结构为:
struct SDS<T> {
T capacity; //数组容量
T len; //数组长度
byte flags; //特殊标志位(不用理)
byte[] content; //数组内容
}
其中capacity表示分配给字符串的长度,len表示字符串的实际长度,content表示字符串的实际内容。一般分配给字符串的长度会大于实际长度,会有一定的冗余,这是由于可修改的字符串支持append操作,如果不冗余则需要重新分配新的数组,然后将旧内容复制过来后再append新的内容,当字符串长度非常长时,这个过程的开销就会非常大。
另外上面的结构使用泛型T的原因在于当字符串比较短时,len和capacity可以为byte和short来表示,这样可以对内存做到极致优化。
存储方式
Redis 的字符串有两种存储方式,分别为embstr形式(字符串长度特别短时)和raw形式(字符串长度超过44字节时)。
1、区别
两种存储方式的区别主要在于Redis对象的头结构和实际的SDS结构体的存放位置。对于embstr方式,其头结构和SDS结构体存放在一起,是一个连续的内存空间;而raw方式则不是存放在一起,内存上是不连续的。
2、临界值的由来
至于为何两种方式的临界值为44字节,那是由于分配内存大小的单位是2/4/8/16/32/64字节等,Redis会将超过64字节的字符串认为是大字符串,故embstr形式分配的最大字节数为64,除去Redis对象头部结构占用的16字节和SDS结构体占用的3字节以及表示字符串结尾的NULL(1字节),字符串的最大长度为44字节。
扩容策略
当字符串长度小于1MB时,扩容空间采用加倍策略。
当字符串长度大于1MB时,每次扩容只会多分配1MB大小的冗余空间。
另外Redis字符串的长度不得超过512MB.