Redis---1.数据结构特点与操作

Redis

Redis:全称Remote Dictionary Service,远程字典服务。

1. Redis基础数据结构

Redis的所有数据结构都是以一个唯一的字符串作为key,然后通过去这个key去获取不同的数据结构。

基础数据结构分成5种:

  • string:字符串
  • list:列表
  • hash:哈希
  • set:集合
  • Zset:有序集合

1.1 string(字符串)

1.1.1 概念

Redis的字符串有len(长度)和cap(容量)的概念,len是字符串实际长度,cap是字符串的容量。当cap大小小于1m时,每次增加都会翻倍,超过1m时则会每次增加1m,cap的最大值为512m。

Redis字符串采用预分配冗余空间的方式(cap > len),避免了内存的频繁分配。

1.1.2 操作

字符串类型的操作
对单个字符串K-V进行修改,getset命令

# key-value的增删改查
>set key value #新增和修改
OK
>get key	#查询value
"value"
>exiist key #查询key
(integer) 1
>del key	#删除key
(integer) 1
>get key   #删除后查询不到
(nil)

批量键值对设置获取
命令mget,mset

>mset name1 11111 name2 22222 name3 33333
OK
>mget name1 name2 name3
"11111"
"22222"
"33333"

expire,key过期时间设置以及setexsetnx set命令的扩展

#key过期时间设置
>set name "test"
OK
>get name 
"test"
>expire name 5 # 单位为秒
#wait for 5s
>get name 
(nil)
#set扩展
>setex name 5 "test" # 在设置的同时设置过期时间
>setnx name "test" # 设置key,存在则设置失败,不存在则设置成功

自增命令incrincrby,使用于value是整数。自增的范围是signed long的最大值和最小值

>set name 5
OK
>get name
5
>incr name
>get name
6
>incrby name 5
>get name
11
>incrby name -5
>get name
6

bitmap:一个字符串由字节组成,1个字节有8个bit组成,所以一个字符串有多个bit组成,这就是bitmap数据结构。

1.2 list(列表)

1.2.1 概念

Redis的列表相当于Java的LinkedList,他是一个链表而不是数组,链表特性就是增加和删除很快O(1)。但是寻找具体位置很慢O(n)。

当列表弹出最后一个元素的时候,该数据结构自动被删除,内存被回收。

List数据结构常用于做异步队列,将需要延后处理的结构体序列化成字符串塞进redis的列表,另一个线程从列表中轮询数据进行处理。

1.2.2 操作

rpushrpop以及lpop
Redis中都是以rpush来构建。根据rpoplpop取不同方向的数据。rpop取先存进list的数,类似队列,先进先出的特点,lpop先去后面存入list的数据,类似栈,先进后出。

> rpush books Math English Golang
(integer) 3
> llen books
(integer) 3
> rpop books
"Golang"
> lpop books
"Math"

lindex,相当于Java中连表里的get(int index)操作,需要对链表进行遍历,然后取第几个的值。
ltrim,保留区间内的,去除区间外的,获取到一个新的链表。
lrange,打印区间内的值

> rpush days Monday Tuesday Wednesday Thursday Friday Saturday Sunday 	#生成一个新的rpush
(integer) 7
> llen days
(integer) 7
> lindex days 2 	#获取下标为2的值
"Wednesday"
> lindex days 0		#下标是由0开始的
"Monday"
> llen days
(integer) 7
> lrange days 0 -1		#-1是倒数第一个数,-2是倒数第二个数
1) "Monday"
2) "Tuesday"
3) "Wednesday"
4) "Thursday"
5) "Friday"
6) "Saturday"
7) "Sunday"
> llen days		
(integer) 7
> ltrim days 1 -1 # 获取从第一个元素到最后一个元素的列表
OK
> llen days		# 已经将原先第0位的Monday去除
(integer) 6
> lrange days 0 -1		#新生成列表2
1) "Tuesday"
2) "Wednesday"
3) "Thursday"
4) "Friday"
5) "Saturday"
6) "Sunday"
> ltrim days 1 -2	# 获取新生成列表2从第一个元素到最后二个元素的列表就是从Wednesday到Saturday
OK
> llen days	
(integer) 4
> lrange days 0 -1 # 遍历列表,发现已经将原来的
1) "Wednesday"
2) "Thursday"
3) "Friday"
4) "Saturday"

list底层初解
当列表元素较少的时候使用的是ziplist,通过将元素压缩存储在一个连续的内存上进行存储,当元素较多的时候使用的是quicklist,通过链表和ziplist结合起来,通过将多个ziplist进行双向串联,避免了普通链表的空间浪费和内存碎片化的问题。

1.3 hash(字典)

1.3.1 概念

Redis中的字典相当于Java中的HashMap,
相同点:数组结合链表,无序。
不同点:Redis中hash的值只能存储字符串。Java的rehash操作是allin,一次性全部进行rehash,redis是渐进式rehash,在渐进式rehash中会在rehash中保留新旧两个hash,然后查询时查询两个,在后续才会将旧hash的内容慢慢同步到新hash中,当移除最后一个旧hash后,原数据结构会被删除。

hash的优点,在存储的时候可以对一个对象的不同字段进行分开存储,而字符串存储的时候需要将整个对象进行存储,在复杂对象存取上 消耗小于字符串

而对于单个字符串的情况,hash结构的存储消耗会高于单个字符串的消耗。

1.3.2 操作

hgethsethgetallhmset,
hget:获取单个key对应的value。
hset:设置一个k-v键值对。
hgetall:获取该key下的所有value。
hmset:设置多个k-v键值对。

> hset books java "first book"
1
> hset books golang "second book"
1
> hset books php "third book"
1
> hgetall books
1) "java"
2) "first book"
3) "golang"
4) "second book"
5) "php"
6) "third book"
> hlen book
0
> hget books java
"first book"
> hset books golang "second book" # 更新前后没有改变
0
> hget books golang
"second book"
> hmset books java "update first book" golang "update second book" php "update third book" # 根据key批量修改value
OK
> hgetall books  # 根据key批量获取value
1) "java"
2) "update first book"
3) "golang"
4) "update second book"
5) "php"
6) "update third book"

1.4 Set(集合)

1.4.1 概念

Redus的集合相当于Java里的HashSet,内部的键值对是无序的唯一的,也就是随机去重存入,所有的value都是null

1.4.2 操作

saddspopsmemberssismemberscard

sadd:添加value进入key集合。
spop: 从key集合中取出value。
smembers:展示集合中的所有元素。
sismember:查询该集合中是否存在元素。
scard:统计集合中一共拥有的元素个数。

> sadd member golang
(integer) 1
> sadd member golang
(integer) 0
> sadd member java php python
(integer) 3
> smembers member
1) "java"
2) "python"
3) "golang"
4) "php"
> sismember member java
(integer) 1
> sismember member javas
(integer) 0
> scard member
4
> spop member
"php"
> spop member
"golang"
> spop member
"java"
> spop member
"python"
> spop member
(nil)

1.5 ZSet(有序列表)

1.5.1 概念

ZSet 有两个特点,一是内部的value唯一,二是每个value都有自己的score,通过这个score可以进行排序。同样的当value 都被移除之后,数据结构会被删除,内存自动回收。

1.5.2 操作

zadd:添加元素
zrange:按排序参数进行输出
zrevrange:按排序参数逆序输出
zcard:计数k-v个数
zscore:获取指定k-v的score
zrank:获取该k-v的排名
zrankbyscore:遍历输出score区间内的value,携带参数withscores可以输出value和score。
zrem:移除元素

> zadd items 9.99 "math" # zadd添加元素
(integer) 1
> zadd items 21.11 "chinese"
(integer) 1
> zadd items 101.11 "MaxMoney"
(integer) 1
> zadd items 3033.11 "RMB"
(integer) 1
> zrange items 0 -1  # 遍历范围内的value,按score顺序输出
1) "math"
2) "chinese"
3) "MaxMoney"
4) "RMB"
> zrevrange items 0 -1  # 遍历范围内的value,按score逆序输出
1) "RMB"
2) "MaxMoney"
3) "chinese"
4) "math"
> zcard items # 计算k-v的数量
4
> zscore items "RMB" # 输出k-v对应的score
3033.11
> zrank items "RMB"  # 输出k-v对应的排序,从零开始,顺序
3
> zrank items "math"
0
> zrangebyscore items 0 100 # 遍历score在区间内的value,输出value
1) "math"
2) "chinese"
> zrangebyscore items 0 100 withscores # 遍历score在区间内的value,输出value和score
1) "math"
2) 9.99
3) "chinese"
4) 21.11
> zrem items math		# 移除元素
1
> zrangebyscore items 0 100 withscores # 移除元素后的结果展示,用于对比,展示zrem的作用
1) "chinese"
2) 21.11

1.6 跳跃链表

跳跃连表是ZSet列表的内部数据结构,他基础数据结构是一个普通的链表,将所有的元素串起来。

然后在这些基础链表结点中选择出更高一级的节点,然后将这些更高一级的节点用一个链表穿起来,这

样就会出现一些链表节点可能会身兼数职,即使低级链表的节点也是高级列表的节点。新增的时候新节

点成为身兼数职的节点的概率是随机的。二分递减,最底层也就是所有元素穿起来的一层概率为1,每往上一级概率*0.5。

1.7 容器型数据结构的通用规则

容器型数据结构:

  • list
  • set
  • zset
  • hash

规则1:create if not exists
如果容器不存在,则创建一个新的数据结构。

规则2:drop if no elements
如果容器内元素没有了,那么立即删除元素,释放内存。

1.8 过期时间

Redis中所有的数据结构都可设过期时间,时间一到则会自动删除改k-v对象,而不是只删除一个value。

学习自《Redis深度历险:核心原理和应用实践》

猜你喜欢

转载自blog.csdn.net/Srwici/article/details/121078041