redis7--02数据类型及其常用命令

数据类型

redis支持的数据类型

  • String
    • 字符串
    • 支持序列化
  • List
    • 列表
  • Hash
    • 哈希表
  • Set
    • 集合
  • ZSet
    • 有序集合
  • GEO
    • 地理空间
  • HyperLogLog
    • 基数统计
  • bitmap
    • 位图
  • bitfield
    • 位域
  • Stream

常用key命令

  • 注意,命令不区分大小写,key是区分大小写的
  • help @命令可以查询该命令的详情
  • keys *
    • 查看当前库所有key
    • *也可以换成其他正则表达式
    • 在检索时,若数据量大可能会造成阻塞
  • exists key
    • 判断某个key是否存在
  • type key
    • 查看key类型
  • del key
    • 删除指定key数据
  • unlink key
    • 非阻塞删除,只是将keys从keyspace元数据中删除,真正的删除会在后续异步中进行
  • ttl key
    • 查看过期剩余时间单位为秒,-1为永不过期,-2表示已经过期
    • pttl key
      • 单位为毫秒
  • expire key time
    • 为指定key设置过期时间,单位为秒
    • pexpire key time,单位为毫秒
  • persist key
    • 将指定key设置为永不过期
  • randomkey
    • 随机返回一个key
    • 可以用来判断一个数据库是否为空
  • move key dbindex[0-15]
    • 将当前数据库的key移动给定的数据库
    • 这里的【0-15】是因为redis默认携带16个数据库
  • select bdindex[0-15]
    • 切换数据库【0-15】,默认为0
  • dbsize
    • 查看当前数据库key的数量
  • flushdb
    • 清空当前库
  • flushall
    • 清除所有库

字符串(String)

  • String 类型的value中可以存放任意数据,最大是512M

set

单次设置一个键值对

SET key value [NX | XX] [GET] [EX seconds | PX milliseconds | EXAT unix-time-seconds | PXAT unix-time-milliseconds | KEEPTTL]

可选项

  • NX | XX
    • NX-- 仅当 key 不存在时设置 key:value
    • XX-- 仅当 key 已存在时覆盖value
  • GET
    • 返回在此次set前key所对应的value(若此key无value则返回nil)
  • EX seconds
    • 以秒为单位设置过期时间
  • PX milliseconds
    • 以毫秒为单位设置过期时间
  • EXAT unix-time-seconds
    • 以秒为单位的unix时间戳设置过期时间
    • java获取该时间戳 System.currentTimeMillis()/1000L
  • PXAT unix-time-milliseconds
    • 以毫秒为单位的unix时间戳设置过期时间
    • java获取该时间戳 System.currentTimeMillis()
  • KEEPTTL
    • 对修改的参数也沿用之前的过期时间(不是最开始设置的那个)
    • 若未指定,则赋值过后会将ttl重置为-1(永不过期)

mset

  • mset key value [key value ...]
  • mset会一次性给多个键值对赋值,并且此操作是原子性的
  • 此时指定的参数,如NX也会对所有set有效,当有一个不满足时,由于mset的原子性,会使得所有操作失效

getrange与setrange

  • getrange key startIndex endIndex
    • 该指令会返回对应value字符串在索引范围内的字符
    • 类似java的substring(beginIndex,endIndex)
  • setrange key offset value
    • 从偏移量offset开始,将对应串后续内容覆盖为value

incr与incrby

  • incr key
    • 若key对应的value是number会将该number加1
  • incrby key increment
    • 若key对应的value是number,则将该number加increment
    • incrby也可以换成incrbyfloat表示浮点型

decr与decrby

  • decr key
    • 若key对应的value是number会将该number减1
  • decrby key decrement
    • 若key对应的value是number,则将该number减decrement

strlen

  • strlen key
  • 返回该value字符串长度

append

  • append key value
  • 向该key对应value追加value

列表(List)

  • 底层为双向链表
  • 常用于一对多的情况,例如消息订阅,内容分发
  • 可以通过lpush和lpop实现栈,通过lpush和rpop实现队列(同理也可以实现阻塞式)

lpush/rpush/lrange

  • lpush key element [element...]
    • 将所有指定的值插入到列表的开头
    • 若key不存在则在push之前创建一个空列表
  • rpush key element [element...]
    • 同lpush,不过是插入到末尾
  • lrange key start stop
    • 返回列表中的指定元素
    • 用0,-1来表示整个列表
    • 没有所谓的rrange
    • 使用时注意列表的数据结构为双向链表即可
  • 例:lpush key1 a b c,lrange key1 0 -1输出c,b,a
  • 例:rpush key1 a b c,lrange key1 0 -1输出a,b,c

lpushx/rpushx

  • 同lpush/rpush,只是当目标列表已存在时才会进行插入操作

lpop/rpop

  • lpop key [index]
    • 从队首弹出索引为index的value,默认为0
  • rpop key [index]
    • 从队尾弹出索引为index的value,默认为0

blpop/brpop

  • 同lpop/rpop,单该命令为阻塞式的,当给定列表内无可弹出内容时,则会被该命令阻塞,直到timeout或出现要弹出元素并弹出为止

lindex

  • lindex key index
    • 从队首按照索引获得元素

lrem

  • lrem key count element
    • 用于删除列表中从队首开始count个值为element的数据
lpush key1 a b c a a
lrem key1 2 a
lrange key1 0 -1
#输出 b c a

ltrim

  • ltrim key start end
    • 截取当前列表指定范围索引内容赋给key
lpush key2 a b c d
ltrim key2 0 2
lrange key2 0 -1
# 输出 a b c

rpoplpush/brpoplpush

  • rpoplpush list1 list2
    • 将list1中的队尾元素弹出并将其插入到list2的队首
  • brpoplpush同rpoplpush,为阻塞版本
lpop list1 c b a
lpop list2 b c
rpoplpush list1 list2
lrange list1 0 -1
#输出 c b
lrange list2 0 -1
#输出 a b c

lset

  • lset key index element
    • 将列表索引为index的元素设置为element

linsert

  • linsert key before/after oldElement newElement
    • 在oldElement的前面或者后面插入newElement
lpop key c a
linsert key before a b
lrange key 0 -1
#输出c b a

哈希(Hash)

  • 依旧是key:value的形式,但是value又是一个新的键值对,类似于java中的hashmap
  • Map<String,Map<Object,Object>>
  • 底层数据结构为哈希表数组和链表
  • 可以用来描述单个实体内又存在多个属性的情况,例如购物车功能(用户id为key,商品id为field,商品个数为value)

hset/hget/hmset/hmget/hgetall/hdel

  • hset key field value [field value ...]
    • 生成一个由key指向的hashmap,该map的键值对为field:value
  • hget key field
    • 返回对应map中key为field的value
  • hmget key field [field ...]
    • 一次返回多个指定field的value
  • hgetall key
    • 返回该map中所有键值对
  • hdel key field [field ...]
    • 删除map中键为field的键值对

hlen

  • hlen key
    • 获取该map中键值对的数量

hexists

  • hexists key field
    • 判断该map中是否存在key为field的键值对

hkeys/hvals

  • hkeys key
    • 获取该map中所有的key
  • hvals key
    • 获取该map中所有的value

hincrby/hincrbyfloat

  • hincrby key field increment
    • 将该map中key为field的value加上increment(整数)
    • increment可以为负数,当作是减
  • hincrbyfloat key field
    • 将该map中key为field的value加上increment(浮点数)
    • increment可以为负数,当作是减

hsetnx

  • hsetnx key field value
    • map中若key为field的键值对不存在才插入field:value键值对
    • 若不存在则忽略词条命令

集合(Set)

  • 就是java中的hashset,特征为单值多value,且无重复
  • 底层是由hashmap实现
  • 可以用在,如猜你喜欢,共有好友,抽奖

sadd

  • sadd key member [member ...]
    • 将指定成员添加到set中
    • 若存在则忽略,若不存在则添加

smembers

  • smembers key
    • 返回set中所有的成员

sismember

  • sismember key member
    • 判断member是否为该set成员
    • 若是则返回1,否则返回0

srem

  • srem key member [member ...]
    • 删除set中指定元素

scard

  • scard key
    • 返回set中元素个数

srandmember

  • srandmember key [count]
    • 从set中返回count绝对值个元素,默认为1
    • 若count为整数,则返回不同元素,若大于set长度,则返回所有元素
    • 若count为负数,则可以返回相同元素
    • 注意set是无序不重复集合,返回的元素是随机的
sadd myset one two three
srandmember myset 1
# 返回 one,two,three中的一个,如two
srandmember myset -4
# 返回 4个可重复的元素,如one one one two

spop

  • spop key [count]
    • 从set中随机弹出count个元素,默认为1

smove

  • smove source destination member
    • 将source中的member成员移动到destination中
    • 若destination不存在则会创建一个destination
sadd set1 one two three
sadd set2 one two
smove set1 set2 three
smembers set1
#输出 one,two
smembers set
#输出 one two three

集合运算

sdiff
  • sdiff key [key ...]
    • 将第一个集合与之后的集合做差集运算并返回
sadd set1 a b c d
sadd set2 a b
sadd set3 a b c
sdiff set1 set2 set3
#输出 d
sunion
  • sunion key [key ...]
    • 返回这些set的并集
sadd set1 a b
sadd set2 a b c
sunion set1 set2
#输出 a,b,c
sinter
  • sinter key [key ...]
    • 返回所有set的交集
sadd set1 a b
sadd set2 a b c
sinter set1 set2
#输出 a,b
sintercard
  • sintercard numkeys key [key ...]
    • 从redis7开始使用
    • 返回所有set的交集的不重复元素个数
    • numkeys指定有几个集合
sadd set1 a b
sadd set2 a b c
sintercard set1 set2
#输出 2

有序集合(ZSet)

  • 可以用于各种需要排序的场景,如商品销量排序,打赏数额排序
  • 它是根据一个额外的属性score来进行排序的

zadd

  • zadd key [nx | xx] [gt | lt] [ch] [incr] score member [score member ...]
    • 将具有排序依据score的member添加到有序集合中,一次可以添加多条数据
    • score是一个double
    • 若member已经存在该有序集合中,则按照score来将其放到新的位置,保证排序正确
    • nx
      • 只添加元素,不更新
    • xx
      • 只更新元素,不添加
    • gt
      • 当new score大于old score才更新,不会阻止添加
    • lt
      • 当new score小于old score才更新,不会阻止添加
    • ch
      • 返回新增成员的个数
    • incr
      • 用于更新已有member的score,同时避免member不存在时会出现的新增成员

zrange

  • zrange key start stop [byscore | bylex] [rev] [limit offset count] [withscores]
    • 返回有序集合中指定索引范围的元素
    • byscore
      • 返回指定score范围的元素
      • inf表示无穷,可以用 -inf +inf来遍历所有scro
      • 在指定范围时,用圆括号来指定是否包含该数
      • 例:(1 5 为1<score<=5
    • bylex
      • 当所有成员的scroe相同,则根据成员的字典排序来进行排序
    • rev
      • 将结果降序排列(默认为升序)
    • limit offset count
      • 用于限制返回元素个数
      • 例:zrange key (10 20 byscore limit 1 1该语句为返回10<score<=20的从索引为1开始的1个元素
    • withscores
      • 在输出value的同时也输出score

zscore

  • zscore key member
    • 用于返回指定成员的score

zcard

  • zcard key
    • 用于返回集合中元素的个数

zrem

  • zrem key member
    • 删除指定member的条目

zincrby

  • zincrby key increment member
    • 为zset中指定元素的score增加increment
    • increment可以为负数表示减

zcount

  • zcount key min max
    • 返回指定score范围的元素个数

zmpop

  • zmpop numkeys key [key] <min | max> [count]
    • 从指定的numkeys个有序列表中弹出最大/最小的count个元素
    • 若集合列表中存在相同score元素,则会随机弹出
    • 例:zmpop 2 key1 key2 min [3] 弹出key1,key2中score最小的三个元素

zrank

  • zrank key member [withscore]
    • 返回指定元素的索引,升序排列
    • withscore
      • 同时返回score

zrevrank

  • 同zrank,不过是降序

位图(bitmap)

  • 就相当于是c语言中的bit位,可以作为状态机使用,比如签到
  • 底层是用String类型实现的,只是不用char作为单位而是用byte
  • 主要用于大数据量的二值性统计

setbit

  • setbit key offset value
    • 设置或清除在key处的字符串值中offset处的位

getbit

  • getbit key offset
    • 返回offset处位的值

bitcount

  • bitcount key [start end [byte | bit]]
    • 返回位图中指定范围内值为1的位数
    • start
      • 开始索引
    • end
      • 结束索引
    • byte
      • 按字节统计
    • bit
      • 按位统计
setbit bitmap 0 1
setbit bitmap 2 1
bitcount bitmap 0 1 byte
# 由于这只有3位,而一个byte有8位,故输出2
bitcount bitmap 0 1 bit
# 输出1

strlen

  • strlen key
    • 统计该位图占用字节数(一个字节为8位)

bitop

  • bitop <and | or |xor |not> destkey key [key ...]
    • 对不同key对应的位图进行按位计算,并将计算结果存储到destkey中

基数统计(HyperLogLog)

  • 基数,即不重复的元素个数
  • HyperLogLog只会根据输入元素计算基数,不会存储元素本身。在输入元素的数量非常大时,计算基数所需的空间总是一个固定的小值(12kB),会有0.81%的误差。
  • 可以用于网站访问次数(列如淘宝等购物网站每日亿级)

pfadd

  • pfadd key element [element]
    • 添加指定元素到hyperloglog中

pfcount

  • pfcount key [key ...]
    • 返回基数的估计值

pfmerge

  • pfmerge destkey sourcekey [sourcekey]
    • 将多个hyperloglog合并为一个(destkey)

地理空间(GEO)

本质上任然是一种集合

geoadd

  • geoadd key [nx | xx] [ch] longitue latitude member [longitude latitude member ...]
    • 将指定地理空间项(经度,纬度,名称)添加到指定的键中。数据作为拍续集和存储到键中
    • 如果这里使用了中文,出现乱码问题,那么在登录redis时需要设置编码 --raw
    • XX
      • 只更新已存在的元素,不添加元素
    • NX
      • 不更新元素,只提那就新元素
    • ch
      • 将返回值从添加的新元素修改为已修改元素的总数

geopos

  • geopos key [member [member ...]]
    • 返回指定member名称的地理位置

geohash

  • geohash key [member [member]]
    • 返回指定成员地理坐标的hash值

geodist

  • geodist key member1 member2 [M| KM | FT | MI]
    • 返回两个成员之间的距离
    • M:米
    • KM:千米
    • MI:英里的米
    • FT:步数

georadius

  • geosearch key <frommember member | fromlonlat longitude latitude> <byradius radius <m | km | ft | mi> | bybox width height <m | km | ft | mi>> [asc | desc] [count count [any]] [withcoord] [withdist] [withhash]
    • 返回圆形或矩形指定范围内的成员
    • frommember
      • 将成员作为中心点
      • 后接成员名
    • fromlonlat
      • 将坐标作为中心点
      • 后接坐标点
    • byradius
      • 圆形范围,后接距离和单位
    • bybox
      • 矩形范围,后接距离和单位
    • withdist
      • 同时返回成员与中心点的距离,单位同之前指定单位
    • withcoord
      • 同时返回匹配项目经纬度
    • withhash
      • 返回项目原始geohash编码的排序集score
    • asc
      • 相对于中心点由近到远排序
    • desc
      • 相对于中心点由远到近排序
    • count
      • 指定返回匹配项个数
geoadd space 11 33 space1 12 35 space2 21 43 space3
geosearch space fromlonlat 13 31 byradius 300 km asc withdist
#输出space1 291.6596

流(Stream)

  • 该流与java中的流完全不相干
  • 此处的reids流是redis版本的mq消息中间件

xadd

  • xadd key [nomkstream] [<maxlen | minid> [= | ~] threshold [limit count]] <* | id> field value [field value ...]
    • 将指定的流数据附加到该key对应流的指定处
    • 若key不存在则会根据该数据创建一个新的流
    • nomkstream
      • 只附加,不创建
    • *
      • 指定redis生成id
      • 生成的id有两段,第一段为unix时间戳,第二段为序列号
    • id
      • 提供给定的id
      • 当前id一定要比上一id大

xrange

  • xrange key start end [count]
    • 返回指定id范围内的数据条目数
    • 小端开始返回
    • start表示开始值,-表示最小值
    • end表示结束值,+表示最大值
    • count
      • 表示返回条目个数

xrevrange

  • xrange key end start [count]
    • 同xrange,不过是从相反顺序返回
    • 大端开始返回

xdel

  • xdel key id [id ...]
    • 从流中删除指定id的条目,并返回条目数删除

xlen

  • xlen key
    • 返回流中的条目数

xtrim

  • xtrim key <maxlen | minid> [= | ~] threshold [limit count]
    • 删除流中低id的条目,修剪流
    • maxlen
      • 指定保留流的条目长度
      • 由新到旧排列
    • minid
      • 指定保留流的条目中最小的id
      • 小于该id的会被删除
    • =
      • 表示严格等于
    • ~
      • 表示近乎精确(存在很小的误差,但是提高性能)

xread

  • xread [COUNT count] [BLOCK milliseconds] sstreams key [key... ] id [id ...]
    • 从一个或多个流中读取数据,只会返回大于指定id的信息
    • $代表最大id,0-0代表最小id
    • COUNT
      • 读取消息数
    • BLOCK
      • 采用阻塞方式读取消息
      • 默认不阻塞
      • 若milliseconds设置为0则表示永远阻塞

xgroup create

  • xgroup create key group <id | $> [MKSTREAM] [ENTRIESREAD entries-read]
    • 创建一个消费组
    • <id | $>
      • 指定id,若0则表示从开始处进行消费
      • 指定$,则表示从结尾处开始消费

发布/订阅消息

消息系统

发布/订阅,即pub/sub,是一种消息通讯模式:发布者也称为消息生产者,生产和发送消息到存储系统;订阅者也称为消息消费者,从存储系统接收和消费消息。

消息系统中的订阅者订阅了某类消息后,只要存储系统中存在该类消息,其就可不断的接收并消费这些消息。当存储系统中没有该消息后,订阅者的接收、消费阻塞。而当发布者将消息写入到存储系统后,就会立即唤醒订阅者。当存储系统放满时,不同的发布者具有不同的处理方式;有的会阻塞发布者的发布,等待可用的存储空间;有的则会将多余的消息丢失。

在RocketMQ、kafka等消息中间件的消息是以主体Topic分类的。而Redis构成的消息系统中,发布/订阅的消息都是以频道Channel分类的

subscribe

  • subscribe channel [channel ...]
  • 阻塞式订阅名为channel的频道

psubscribe

  • psubscribe pattern [pattern ...]
  • 订阅符合给定模式的频道
  • 这里的通配符pattern只能使用*来进行模糊匹配,如以my为开头的频道my*

publish

  • publish channel message
  • 发布一个名为channel的message消息,返回值为接收到的订阅者数量

unsubscribe

  • unsubscribe [channel [channel ...]]
  • redis客户端退订指定频道
  • 若未指定参数则全部退订

punsubscribe

  • punsubscribe [pattern [pattern ...]]
  • 退订符合给定模式的频道

pubsub

  • pubsub [channels [pattern]] [numsub [channel-1 ... channel-n]] [numpat]
    • pubsub channels [pattern]
      • 列出当前所有的活跃频道(存在订阅者的频道)
      • pattern参数用于指定给定模式,同样只能用通配符*
    • pubsub numsub [channel-1 ... channel-n]
      • 返回给定频道的订阅者数量
    • pubsub numpat
      • 查询当前redis所有客户端订阅的所有频道模式的数量总和

redis事务

redis的事务本质上是一组批处理命令,这组命令在执行过程中会被顺序地、一次性全部执行完毕,只要没出现语法错误,这组命令在执行期间不会被中断

redis事务特性

  • redis的事务只保证了数据的一致性,不具有DBMS的ACID特性
  • 事务的批处理命令中的某些命令的执行失败不会影响其余命令的执行,不会引发回滚,不具有原子性
  • 这组命令通过乐观锁机制实现了简单的隔离性
  • 这组命令的执行结果是被写入到内存的,是否持久化取决于redis的持久化策略,与事务无关

redis事务实现

muti开启事务,exec执行事务,discard取消事务

例:下面两个客户端发送命令的时间一一对应,模拟并发,假设redis中已经对k进行了如下定义set k 1 watch k # 为k添加乐观锁

# 客户端1
get k #输出1
mutil
incr k 10
get k
exec
# 输出nil 21
# 客户端2
get k #输出1
incr k 20
get k # 输出21

在该例子中k的值为1,并对其加上了乐观锁,此时k的版本号为1,当客户端2对其进行修改时使其版本号变为了2,此时客户端1只是开启了事务,还未对事务进行编写与执行。之后,客户端2调取k的值为21。最后客户端1执行事务,在修改k时发现版本号不匹配,抛出了nil表示修改失败,随后查看k的值,发现为客户端2修改后的21

简单动态字符串SDS

简介

  • redis的key和value其基础数据类型都是字符串,如hash-value-field,list,set,zset
  • 该字符串并非C语言样的传统的字符串。而是简单动态字符串SDS

SDS结构

struct sdshdr {
  // 保存字符串
  // 若该变量存放的仍然为字符串,则也是由'\0'结尾
  char buf[];
  // 保存buf已使用的字节数量,不包括串尾的'\0'
  int len;
  // 保存buf未使用字节数量
  int free
}

变量len与free的作用

  • 加快访问速度
    • 对于c获取字符串长度需要遍历数组,会造成时间上浪费,此处用int类型变量len空间去换得遍历数组的时间
  • 保证二进制安全
    • 用len来标记字符串长度,而不是通过’\0’,使得该结构具有了二进制安全性,即不会因为存在’\0’的二进制编码而导致读取中断,保证了读出与写入数据的一致性,可以用来存储图片、视频、office等二进制文件
  • 减少内存再分配次数
    • 每次sds进行空间扩展时,会为其分配额外空间以减少分配次数
    • 当len的值小于1m,那么分配未使用空间free大小与len值相同(注意,这里指的是进行添加后的len长度)
    • 当len的值大于1m,那么分配未使用空间free大小固定为1M
    • 当sds串长度缩短,则多出的空间将不会被释放,而是被增加到free中

常用的sds操作函数

  • sdsnew()
    • 使用指定的c字符串创建一个sds
  • sdsempty()
    • 创建一个不包含任何字符串数据的sds
  • sdsdup()
    • 创建一个指定sds的副本
  • sdsfree()
    • 释放指定的sds
  • sdsavail()
    • 获取指定sds的未使用空间free值
  • sdsMakeRoomFor()
    • 使指定sds的free空间增加到指定大小
  • sdsRemoveFreeSpace()
    • 释放指定sds的free空间
  • sdscat()
    • 将指定的c字符串拼接到指定sds字符串末尾
  • sdscatsds()
    • 将指定的sds字符串拼接到另一给指定sds字符串末尾
  • sdscpy()
    • 将指定的c字符串赋值到指定sds中,覆盖原有sds字符串内容
  • sdsgrouzero()
    • 扩展sds字符串到指定长度,使用’\0’填充
  • sdsrange()
    • 截取指定sds中指定范围内的字符串
  • sdstrim()
    • 在指定sds中收删除所有指定c字符串中出现的所有字符
  • sdsemp()
    • 对比两个给定的sds串是否相同
  • sdstolow()
    • 将指定sds串中的所有字母变为小写
  • sdstoupper()
    • 将指定sds串中的所有字母变为大写

集合的底层实现原理

  • 对于set而言,其底层使用的为hashset。
  • 而hash与zset集合,其底层实现分为两种,分别为压缩列表zipList与跳跃列表skipList,实现何种列表对于用户来说是透明的,系统会根据用户的输入来使用不同的实现。(1.集合元素个数小于redis.conf中zset-max-ziplist-entries属性的值,默认为128;2.每个集合元素大小都小于redis.conf中zset-max-ziplist-value属性的值,默认为64字节)当同时满足两点,则使用压缩列表zipList,其余情况下使用跳跃列表skipList
  • list的底层实现为quickList

zipList

称为压缩列表,是一个经过特殊的用于存储字符串或整数的双向链表,其底层数据结构由三部分组成:head,entries与end。这三部分在内存上是连续存放的

  • head
    • 由三部分组成,分别是
    • zlbytes
      • 占4字节,用于存放zipList列表整体数据结构所占用的字节数
    • zltail
      • 占4字节,用于存放zipList中最后一个entry在整个数据结构中的偏移量(字节)。该数据结构的存在可以快速定位列表的尾部entry位置
    • zllen
      • 占2个字节,用于存放列表包含的entry个数
  • entries
    • 是真正的列表,由很多列表元素entry构成。
    • 每个entry由三部分构成
    • prevlength
      • 用于记录上一个entry长度,以实现逆序遍历。默认长度为1字节,若上一个entry长度<254字节,prevlength就占1字节,否则其会自动扩展为3字节长度
      • 由于该结构在进行数据更新时会出现级联操作,在redis7以后zipList完全被listPack取代
    • encoding
      • 用于标志后面的data的具体类型,若为整数类型,encoding固定长度为1字节。若为字符串类型,则encoding长度可能是1,2,5字节。
    • data
      • 真正存储的数据,数据类型只能是整数类型或字符串类型。不同的数据占用的字节长度不同
  • end
    • 只包含一个部分,zlend,占1字节,固定全1,表示结束

listPack

在redis7中listPack已经完全取代了zipList,为了兼容任然保留了zipList。listPack同样也是由head,entries,end三部分组成。listPack与zipList的重大区别在于head与每个entry的结构上,表示列表结束的end与zipList的zlend是相同的,占1个字节,且8位全为1

  • head
    • 由两部分组成
    • 与zipList的head相比,取消了记录最后一个entry偏移量的zltail
    • totalBytes
      • 占4字节,用于存放listPack列表整体数据结构所占字节数。
    • elemNum
      • 占2字节,用于存放列表包含的entry个数。
      • 其意义与zipList中zllen相同
  • entries
    • 与zipList的该部分相比,其最大变化在于取消了记录前一个entry长度的prevlength,而增加了记录当前entry长度的element-total-len,通过此项改变解决了改变entry时会引发的级联更新
    • encoding
      • 用于标志后面的data具体类型,若为整数类型,其固定长度可能为1、2、3、4、5、9字节。不同的字节长度,其标识位不同。若data为字符串类型,则encoding长度可能是1、2、5字节。
    • data
      • 真正存储的数据,数据类型只能是整数类型或字符串类型。不同的数据占用的字节长度不同
    • element-total-len
      • 记录当前entry的长度,用于实现逆序遍历。由于其特殊的记录方式,使其本身占有的字节数据可能会是1、2、3、4、5字节

skipList

称为跳跃列表,简称跳表,用并联链表的空间来换取顺序查找的时间。是一种随机化的数据结构,基于并联的链表。使得在查询元素时能够提供较高的效率。其原理可以用二分查找来类比,通过并联的节点来实现跳跃访问,再根据跳跃前和跳跃后的节点值来判断目标节点是否在二者之间,若在则访问二者之间的节点,若不在,则继续向前进行跳跃

quickList

是list类型的底层实现,quickList,快速列表,其本身是一个双向无循环链表,它的每一个节点都是一个zipList。在每个zipList中又存放了多条真正的数据。对于每个zipList中最多可存放多大容量的数据元素在配置文件中可以通过list-max-ziplist-size属性进行指定。

当进行插入操作时要注意该结构可能导致的元素转移问题(可以看作是由双向链表链接的有序数组)。

  • 当插入到一个zipList首部,空间不足则看上一个节点空间是否充足,若还是不足则新建一个节点插入到两节点之间
  • 当插入到一个zipList尾部,空间不足则看下一个节点空间是否充足,若还是不足则新建一个节点插入到两节点之间
  • 当插入到一个zipList中间,空间不足则将该zipList在该节点位置处分隔成两个zipList。然后再将该元素插入到前一个zipList的尾部
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值