redis中其他几种数据类型:
【List类型使用及底层结构】
【hash类型使用及底层结构】
【set类型使用及底层结构】
【Zset类型使用及底层结构】
一、简单使用
1.基本用法
#值的基本设置与获取
127.0.0.1:6379> set k1 v1 #给k1设置值v1
OK
127.0.0.1:6379> get k1 #获得k1对应的值
"v1"
127.0.0.1:6379> keys * #获得所有的key
1) "seckillGoods:1"
2) "seckillGoods:2"
3) "user:9d6ca146f0f049c29029649e8cad042c"
4) "k1"
5) "user:a9540871920043a2a7d4c834d67762c7"
6) "name"
127.0.0.1:6379> exists k1 #判断k1是否存在
(integer) 1
127.0.0.1:6379> append k1 hello #将hello添加到k1对应的值v1后面,如果当前key不存在相当于set
(integer) 7
127.0.0.1:6379> get k1
"v1hello"
127.0.0.1:6379> strlen k1 #获得k1对应的值v1的长度
(integer) 7
127.0.0.1:6379>
----------------------------------------------------------------------------
#数据自增
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> incr views #自增1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> decr views #自减1
(integer) 1
127.0.0.1:6379> incrby views 10 #设置步长(10),指定增量
(integer) 11
127.0.0.1:6379> get views
"11"
127.0.0.1:6379> decrby views 2 #自减特定的步长(2)
(integer) 9
127.0.0.1:6379> get views
"9"
------------------------------------------------------------------------------
#截取指定范围字符串
127.0.0.1:6379> set key1 "hello,i am lihua"
OK
127.0.0.1:6379> getrange key1 0 4 #通过getrange截取指定下标字符串,闭区间!
"hello"
127.0.0.1:6379> getrange key1 0 -1 #0 ~ -1表示完整字符串
"hello,i am lihua"
#替换指定范围字符串
127.0.0.1:6379> set key2 abcdefg
OK
127.0.0.1:6379> setrange key2 1 xx #1表示从下标1开始替换,xx表示替换的值
(integer) 7 #xx有多少位,就会从1开始向后替换多少位
127.0.0.1:6379> get key2
"axxdefg"
127.0.0.1:6379>
----------------------------------------------------------------------------------
#设置过期时间
#setex(set with expire) #设置过期时间
#setex key time value #time表示过期时间
127.0.0.1:6379> setex key3 30 hello
OK
127.0.0.1:6379> ttl key3
(integer) 17
#setnx(set if not exist) #不存在则设置,如果存在则设置失败(常用于分布式锁)
#直接set的话,如果该key存在则会覆盖之前的value
127.0.0.1:6379> setnx key4 xiaoming
(integer) 1 #返回1表示操作成功,返回0表示操作失败
127.0.0.1:6379> get key4
"xiaoming"
127.0.0.1:6379> setnx key4 xiaohong
(integer) 0
127.0.0.1:6379> get key4
"xiaoming"
127.0.0.1:6379>
-----------------------------------------------------------------------------------
#批量设置和获取
#mset key1 value1 key2 value2...
#mget key1 key2...
#msetnx 不存在则设置
127.0.0.1:6379> mset k2 v2 k3 v3
OK
127.0.0.1:6379> mget k2 k3
1) "v2"
2) "v3"
-----------------------------------------------------------------------------------
#对象的设置
set user:1 {name:zhangsan,age:3} #设置一个key为user:1,value为json字符串保存一个对象
# “:”和mset的巧妙使用 user:{id}:{filed}
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "2"
127.0.0.1:6379>
--------------------------------------------------------------------------------------
#一个组合命令
getset #先get后set
127.0.0.1:6379> getset db redis #如果不存在,则返回nil
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongodb #如果存在值,获取原来的值,并设置新的值
"redis"
127.0.0.1:6379> get db
"mongodb"
2.使用场景
- 计数器
- 对象缓存存储
二、底层结构
首先我们要知道,C语言的字符串是存在一些不足的:
- 获取字符串长度的时间复杂度为 O(N),因为 需要遍历;
- 字符串的结尾是以 ‘\0’ 字符标识,字符串里面不能包含有 ‘\0’ 字符,因此不能保存二进制数据;
- 字符串操作函数不高效且不安全,比如有缓冲区溢出的风险,有可能会造成程序运行终止;
而redis为了解决上面的问题,自己设计了一个名为SDS(simple dynamic string)的字符串结构。
1.结构设计
-
len:记录了字符串长度。
-
**alloc:分配给字符数组的空间长度。**在修改字符串的时候,可以通过
alloc - len
计算出剩余的空间大小,可以用来判断空间是否满足修改需求,如果不满足的话,就会自动扩容。 -
flags:用来表示不同类型的 SDS。一共设计了 5 种类型,分别是 sdshdr5、sdshdr8、sdshdr16、sdshdr32 和 sdshdr64。
-
buf[]:字符数组,用来保存实际数据。不仅可以保存字符串,也可以保存二进制数据。
2.问题解决
-
O(1)复杂度获取字符串长度。
直接返回len变量的值就好。
-
二进制安全。
SDS 改进后,不需要用 “\0” 字符来标识字符串结尾了,用len变量记录长度就可以,所以可存储包含 ‘\0’的数据。
-
不会发生缓冲区溢出。
当空间不足时会自动进行扩容。
-
节省内存空间。
通过不同类型的结构体,可以灵活保存不同的字符串,有效节省了空间。
参考[小林coding]