Redis 的五大基本数据类型操作

2、Redis 的五大基本数据类型

注:这里说的数据类型是 Value 的数据类型,Key 的类型都是字符串类型;

Redis 中的五种基本数据类型:

  • 字符串:String
  • 列表:List
  • 集合:Set
  • 哈希表:Hash
  • 有序集合:Zset

Redis中常用数据类型操作命令:http://redis.cn/commands.html

2.1、Redis 中对键(Key)的操作

命令解释
keys *查看当前库所有的key
exists key判断某个key是否存在
type key查看你的key是什么类型
del key删除指定的key数据
unlink key与 del key 类似,del key 为同步删除,unlink key 为异步删除;
建议:删除 Redis 中的大 Key 时,使用 unlink key,否则使用 del key
expire key 10为指定的key设置有效期10秒
ttl key查看指定的key还有多少秒过期,-1:表示永不过期,-2:表示已过期
select dbindex切换数据库【0-15】,默认为0
dbsize查看当前数据库key的数量
flushdb清空当前库
flushall通杀全部库

2.2、Redis 中的字符串类型操作(String)

2.2.1、简介

String 是 Redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。

String 类型是二进制安全的。意味着 Redis的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象。

String 类型是 Redis 最基本的数据类型,一个 Redis 中字符串 value 最多可以是 512M

2.2.2、常用命令

操作作用
set添加键值对
get获取 key 对应的值
apend将给定的 value 追加到原值的末尾。
strlen获取 key 对应的值的长度
setnx当 key 不存在时,设置 key 的值
incr将 key 中存储的值加 1,只能对数字值操作,如果为空,新增值为 1
decr将 key 中存储的值减 1,只能对数字值操作,如果为空,新增值为 -1
incrby将 key 中存储的数字值递增指定的步长,若 key 不存在,则相当于在原值为 0 的值上递增指定的步长。
decrby将 key 中存储的数字值递减指定的步长,若 key 不存在,则相当于在原值为 0 的值上递减指定的步长。
mset同时设置多个 key-value
mget同时获取多个 key 的值
msetnx当多个 key 均不存在时,则设置成功
getrange类似 java 中的 substring
setrange覆盖指定位置的值
setex设置键值,并设置过期时间
getset以旧换新,设置新值同时返回旧值
set 添加键值对
127.0.0.1:6379> set key value [EX seconds|PX milliseconds|EXAT timestamp|PXAT milliseconds-timestamp|KEEPTTL] [NX|XX] [GET]

NX:当数据库中 key 不存在时,可以将 key-value 添加到数据库

XX:当数据库中 key 存在时,可以将 key-value 添加数据库,与 NX 参数互斥

EX:key 的超时秒数

PX:key 的超时毫秒数,与 EX 互斥

value 中若包含空格、特殊字符,需用双引号包裹

get 获取值
127.0.0.1:6379> get <key>
apend 追加值
# 将给定的value追加到原值的末尾。
127.0.0.1:6379> append <key> <value>
strlen 获取值的长度
127.0.0.1:6379> strlen <key>
setnx 不存在时,设置 key 的值
# 成功返回 1,失败返回 0;
127.0.0.1:6379> setnx <key> <value>
incr 递增 1
# 将 key 中存储的值减 1,只能对数字值操作,如果为空,新增值为 1
127.0.0.1:6379> incr <key>
decr 递减 1
# 将 key 中存储的值减 1,只能对数字值操作,如果为空,新增值为 -1
127.0.0.1:6379> decr <key>
incrby/decrby 递增/递减 指定数字
# 将 key 中存储的数字值递增指定的步长,若key不存在,则相当于在原值为0的值上递增指定的步长。
127.0.0.1:6379> incrby <key> <步长>
127.0.0.1:6379> decrby <key> <步长>
mset 同时设置多个 key-value
127.0.0.1:6379> mset <key1> <value1> <key2> <value2>
mget 同时获取多个 key 的值
127.0.0.1:6379> mget <key1> <key2>
msetnx 当多个 key 均不存在时,则设置成功
# Redis 操作均为原子性操作,要么都成功,要么都失败
127.0.0.1:6379> msetnx <key1> <value1> <key2> <value2>
getrange 类似 Java 中的 substring
# 获取 [start,end] 返回为的字符串,下标从 0 开始
127.0.0.1:6379> getrange key start end
setrange 覆盖指定位置的值
127.0.0.1:6379> setrange <key> <起始位置> <value>

示例:

127.0.0.1:6379> set k1 helloworld
OK
127.0.0.1:6379> get k1
"helloworld"
127.0.0.1:6379> setrange k1 1 java
(integer) 10
127.0.0.1:6379> get k1
"hjavaworld"
setex 设置键值,并设置过期时间
127.0.0.1:6379> setex <key> <过期时间()> <value>
getset 以旧换新,设置新值同时返回旧值
# 如果旧值未设置过,就返回 null
127.0.0.1:6379

2.2.3、数据结构

String 的数据结构为简单动态字符串(Simple Dynamic String,缩写SDS)。是可以修改的字符串,内部结构上类似于 Java 的 ArrayList,采用分配冗余空间的方式来减少内存的频繁分配。

1661754275953)(../../image/image-20220826153310710.png)]

如图所示,内部为当前字符串实际分配的空间 capacity 一般要高于实际字符串长度 len。当字符串长度小于 1M 时,扩容都是加倍现有的空间,如果超过 1M,扩容时一次会多扩容 1M 的空间。

注:字符串最大长度为 512M。

2.3、Redis 中的列表类型操作(List)

2.3.1、简介

redis列表是简单的字符串列表,按照插入顺序排序。

你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

它的底层实际上是使用双向链表实现的,对两端的操作性能很高,通过索引下标操作中间节点性能会较差。

2.3.2、常用命令

操作作用
lpush从左边插入一个或多个值
rpush从右边插入一个或多个值
lrange从列表左边获取指定范围的值
lpop从左边弹出多个元素
rpop从右边弹出多个元素
rpoplpush从一个列表右边弹出一个元素放到另外一个列表中
lindex获取指定位置的索引
llen获取列表的长度
linsert在某一个值的前/后插入一个值
lrem删除指定数量的某个元素
lset替换指定位置的值
lpush/rpush 从左/右边插入一个或多个值
127.0.0.1:6379> lpush/rpush <key> <value1> <value2>
lrange 从列表左边获取指定范围的值
127.0.0.1:6379> lrange <key> <start> <stop>

返回列表 key 中指定区间 [start, stop] 内的元素,区间以偏移量 start 和 stop 指定。

下标(index)参数 start 和 stop 都以 0 为底,也就是说,以 0 表示列表的第一个元素,以 1 表示列表的第二个元素,以此类推。

你也可以使用负数下标,以 -1 表示列表的最后一个元素, -2 表示列表的倒数第二个元素,以此类推。

返回值:一个列表,包含指定区间内的元素

示例

127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> rpush course java c c++ php js nodejs	#course 集合的右边插入6个元素 
(integer) 6
127.0.0.1:6379> lrange course 0 -1	#取出course集合中所有元素 
"java"
"c"
"c++"
"php"
"js"
"nodejs"
127.0.0.1:6379> lrange course 1 3	#获取 course 集合索引 [1,3] 范围内的元素
"c"
"c++"
"php
lpop/rpop 从左/右边弹出多个元素
127.0.0.1:6379> lpop/rpop <key> <count>

count 可以省略,默认为 1

lpop/rpop 之后,弹出来的值会从 list 中删除

list 为空之后,键会被删除

rpoplpush 从一个列表右边弹出一个元素放到另外一个列表中
# 从 source 的右边弹出一个元素放到 destination 列表的左边,并返回被弹出的值
127.0.0.1:6379> rpoplpush source destination
lindex 获取指定索引位置的元素
# 返回列表 key 中,下标为 index 的元素;
127.0.0.1:6379> lindex key index

index:0:表示第一个元素,-1:表示最后一个元素;

如果 key 不是列表类型,则返回一个错误;

如果 index 超出了列表的范围,则返回 null;

llen 获取列表的长度
# 返回列表的长度;
127.0.0.1:6379> llen key

如果 index 超出了列表的范围,则返回 null;

如果 key 不是列表类型,返回一个错误;

linsert 在某一个值的前/后插入一个值
# 将 newvalue 插入到 value 的前/后;
127.0.0.1:6379> linsert <key> before|after <value> <newvalue>

当 value 不存在时,不做任何操作;

当 key 不存在时,列表为空,不做任何操作;

当 key 不是列表类型时,返回一个错误;

返回值:

  • 命令执行成功,返回插入后的列表长度;
  • vlaue 不存在,返回 -1;
  • key 不存在,或 key 不为列表,返回 0;
lrem 删除指定数量的某个元素
# 根据参数 count 的值,移除列表中与参数 value 相等的元素
127.0.0.1:6379> lrem key count value

count 的值可以是以下几种:

  • count > 0:从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count;
  • count < 0:从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count;
  • count = 0:移除表中所有与 value 相等的值;

返回值:

  • 被移除元素的数量。
  • 因为不存在的 key 被视作空表(empty list),所以当 key 不存在时,总是返回 0 。
lset 替换指定位置的值
# 将列表 key 下标为 index 的元素的值设置为 value 。
127.0.0.1:6379> lset <key> <index> <value>

当 index 参数超出范围,或对一个空列表( key 不存在)进行lset时,返回一个错误;

操作成功返回 ok ,否则返回错误信息。


2.3.3、数据结构

List 的数据结构为快速链表 quickList;首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也就是压缩列表。它将所有的元素紧挨着一起存储,分配的是一块连续的内存。当值比较多的时候才会改成 quickList。因为普通的链表需要的附加指针空间太大,会比较浪费空间,比如这个列表里存储的只是 int 类型的值,结构上还需要 2 个额外的指针 prev 和 next。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-erIFvtjl-1661754275956)(../../image/image-20220826164453099.png)]

redis 将链表和 ziplist 结合起来组成了 quicklist。也就是将多个 ziplist 使用双向指针串起来使用,这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。

2.4、Redis 中的集合类型操作(Set)

2.4.1、简介

redis set 对外提供的功与 list 类似,是一个列表的功能,特殊之处在于 set 是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set 是一个很好的选择。

redis 的 set 是 string 类型的无序集合,他的底层实际是一个 value 为 null 的 hash 表,所以添加,删除,查找复杂度都是O(1)。

一个算法,如果时间复杂度是O(1),那么随着数据的增加,查找数据的时间不变,也就是不管数据多少,查找时间都是一样的。

2.4.2、常用命令

操作作用
sadd添加一个或多个元素
smembers取出所有元素
sismember判断集合中是否有某个值
scard返回集合中元素的个数
srem删除一个或多个元素
spop随机弹出指定数量的元素
srandmember随机获取指定数量的元素,不会从集合中删除
smove将某个元素从一个集合移动到另一个集合
sinter取多个集合的交集
sinterstore取多个集合的交集,放到一个新的集合
sunion取多个集合的并集,自动去重
sunionstore取多个集合的并集,放到一个新的集合
sdiff取多个集合的差集
sdiffstore取多个集合的差集,放到一个新的集合
sadd 添加一个或多个元素
# 向 key 中添加一个或多个元素,并自动去重
127.0.0.1:6379> sadd <key> <value1> <value2>
smembers 取出所有的元素
# 取出 set 集合中所有的元素
127.0.0.1:6379> smembers <key>
sismember 判断集合中是否有某个值
# 判断集合key中是否包含元素value
# 返回值:1 有;0 没有
127.0.0.1:6379> sismember <key> <value>
scard 返回集合中元素的个数
# 返回集合 key 的基数(集合中元素的数量);
# 当 key 不存在时,返回 0;
127.0.0.1:6379> scard <key>
srem 删除多个元素
# 移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略;
# 当 key 不是集合类型时,返回错误;
# 返回被成功移除的元素的数量;
127.0.0.1:6379> srem key member [member ...]
spop 随机弹出多个值
# 随机从 key 集合中弹出 count 个元素,count 默认值为 1;
127.0.0.1:6379> spop <key> <count>

返回被弹出的元素;

当 key 不存在(集合为空)时,返回 null;

当 count 大于集合的长度时,返回所有数据;

srandmember 随机获取多个元素,不会从集合中删除
# 从 key 指定的集合中随机返回 count 个元素,count 可以不指定,默认值是 1。
127.0.0.1:6379> srandmember <key> <count>

srandmember spop的区别:

都可以随机获取多个元素,srandmember 不会删除元素,而spop会删除元素。

返回值:

只提供 key 参数时,返回一个元素;如果集合为空,返回 nil 。

如果提供了 count 参数,那么返回一个数组;如果集合为空,返回空数组

smove 将某个元素从一个集合移动到另一个集合
# 将 member 元素从 source 集合移动到 destination 集合。
127.0.0.1:6379> smove <source> <destination> member

smove 是原子性操作;

如果 source 集合不存在或不包含指定的 member 元素,则 smove 命令不执行任何操作,仅返回 0 。否则, member 元素从 source 集合中被移除,并添加到 destination 集合中去;

如果 destination 集合已经包含 member 元素时,smove 命令只是简单地将 source 集合中的 member 元素删除;

如果 source 或 destination 不是集合类型时,返回一个错误;

返回值:

  • 如果 member 元素被成功移除,返回 1;

如果 member 元素不是 source 集合的成员,并且没有任何操作对 destination 集合执行,那么返回 0;

sinter 取多个集合的交集
127.0.0.1:6379> sinter key1 key2 [key3 ...]
sinterstore 将多个集合的交集放到一个新的集合中
# 这个命令类似于 sinter 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集;
# 返回结果集中的成员数据;
127.0.0.1:6379> sinterstore destination key [key ...]
sunion 去多个集合的并集,自动去重
127.0.0.1:6379> sunion key [key ...]
sunionstore 将多个集合的并集放到一个新的集合中
# 这个命令类似于 sunion 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集;
# 返回结果集中的成员数量
127.0.0.1:6379> sinterstore destination key [key ...]
sdiff 取多个集合的差集
# 如果结果为空,则返回一个空数组
127.0.0.1:6379> sdiff key [key ...]
sdiffstore 将多个集合的差集放到一个新的集合中
# 这个命令类似于 sdiff 命令,但它将结果保存到 destination 集合,而不是简单地返回结果集;
# 结果集中的成员数量;
127.0.0.1:6379> sdiffstore destination key [key ...]

2.4.3、数据结构

set 数据结构是字典,字典是用 hash 表实现的;

Java 中的 HashSet 的内部实现使用 HashMap,只不过所有的 value 都指向同一个对象;

Redis 的 set 结构也是一样的,它的内部也使用 hash 结构,所有的 value 都指向同一个内部值;

2.5、Redis 中的哈希类型操作(Hash)

2.5.1、简介

Redis hash是一个键值对集合;

Redis hash是一个string类型的field和value的映射表,hash特别适合用于存储对象;

类似于java里面的Map<String,Object>;

2.5.2、常用命令

操作作用
hset设置多个 field 的值
hget返回指定的 field 的值
hgetall返回所有的域和值
hmset和 hset 类似(已弃用)
hexists判断给定的 field 是否存在
hkeys返回所有的 field
hvals返回所有的 value
hlen返回 field 的数量
hincrby在 field 的值加上指定的数量
hsetnx当 field 不存在时,设置 field 的值
hset 设置多个 field 的值
# 将哈希表 key 中的域 field 的值设为 value 。
127.0.0.1:6379> hset key field value [field value ...]

如果 key 不存在,一个新的哈希表被创建并进行 hset 操作;

如果域 field 已经存在于哈希表中,旧值将被覆盖;

返回值:

  • 如果 field 是哈希表中的一个新建域,并且值设置成功,返回 1;
  • 如果哈希表中域 field 已经存在且旧值已被新值覆盖,返回 0;
hget 获取指定 field 的值
127.0.0.1:6379> hget key field
hgetall 返回 hash 中所有的域和值
127.0.0.1:6379> hgetall key
hmset 和 hset 类似(已弃用)
127.0.0.1:6379> hmset key field value [field value ...]
hexists 判断给定的 field 是否存在
# 存在返回 1,不存在返回 0
127.0.0.1:6379> hexists key field
hkeys 列出所有的 field
127.0.0.1:6379> hkeys key
hvals 列出所有的 value
127.0.0.1:6379> hvals key
hlen 返回 field 的数量
# 当 key 不存在时,返回 0
127.0.0.1:6379> hlen key
hincrby 在 field 的值加上指定的数量
127.0.0.1:6379> hincrby key field increment

为哈希表 key 中的域 field 的值加上增量 increment 。

增量也可以为负数,相当于对给定域进行减法操作。

如果 key 不存在,一个新的哈希表被创建并执行 HINCRBY 命令。

如果域 field 不存在,那么在执行命令前,域的值被初始化为 0 。

对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。

返回值:

执行 hincrby 命令之后,哈希表 key 中域 field 的值。

hsetnx 当 field 不存在时,设置 field 的值
127.0.0.1:6379> hsetnx key field value

将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在。

若域 field 已经存在,该操作无效。

如果 key 不存在,一个新哈希表被创建并执行 hsetnx 命令。

返回值:

设置成功,返回 1 。

如果给定域已经存在且没有操作被执行,返回 0


2.5.3、数据结构

Hash 类型对应的数据结构是 2 中:ziplist(压缩列表),hashtable(哈希表)。

当 field-value 长度较短个数较少时,使用 ziplist,否则使用 hashtable。

2.6、Redis 中的有序集合操作(Zset)

2.6.1、简介

redis 有序集合 zset 与普通集合 set 非常相似,是一个没有重复元素的字符串集合。

不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。

集合的成员是唯一的,但是评分是可以重复的。

因为元素是有序的,所以你可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。

访问有序集合中的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员你的智能列表。

2.6.2、常用命令

操作作用
zadd添加一个或多个元素
zrange返回指定索引范围的元素(score 升序)
zrevrange返回指定索引范围的元素(score 降序)
zrangebyscore返回指定 score 范围的元素(score 升序)
zrevrangebyscore返回指定 score 范围的元素(score 降序)
zincrby为指定元素的 score 加上指定的数量
zrem删除集合中一个或多个元素
zremrangebyrank删除指定索引范围元素
zrenrangebyscore删除指定 score 范围元素
zcount返回指定 score 范围内元素的个数
zrank返回某个元素在集合中的排名(score 升序)
zrevrank返回某个元素在集合中的排名(score 降序)
zscore返回集合中指定元素的 score
zadd 添加元素
127.0.0.1:6379> zadd <key> <score1> <member1> <score2> <member2> ...

将一个或多个 member 元素及其 score 值加入到有序集 key 当中。

如果某个 member 已经是有序集的成员,那么更新这个 member 的 score 值,并通过重新插入

这个 member 元素,来保证该 member 在正确的位置上。

score 值可以是整数值或双精度浮点数。

如果 key 不存在,则创建一个空的有序集并执行 zadd 操作。

当 key 存在但不是有序集类型时,返回一个错误。

返回值:

被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员

zrange 或者指定索引范围的元素(score 升序)
127.0.0.1:6379> zrange key start top [withscores]
  • 返回存储在有序集合 key 中的指定范围的元素。 返回的元素可以认为是按score从最低到最高排列,如果得分相同,将按字典排序。

  • 下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。

  • 你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。

  • zrange key 0 -1:可以获取所有元素

  • withscores:让成员和它的 score 值一并返回,返回列表以 value1, score1, …, valueN, scoreN 的格式表示

可用版本:>= 1.2.0

**时间复杂度:**O(log(N)+M), N 为有序集的基数,而 M 为结果集的基数。

**返回值:**指定区间内,带有 score 值(可选)的有序集成员的列表。

zrevrange 获取指定索引范围的元素(score 降序)
# 和 zrange 用法一致
127.0.0.1:6379> zrevrange key start stop [WITHSCORES]
zrangebyscore 获取指定 score 范围内的数据(score 升序)
127.0.0.1:6379> zrangebyscore key min max [WITHSCORES] [LIMIT offset count]

返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。

具有相同 score 值的成员按字典序来排列(该属性是有序集提供的,不需要额外的计算)。

可选的 LIMIT 参数指定返回结果的数量及区间(就像SQL中的 SELECT LIMIT offset, count),注意当 offset 很大时,定位 offset 的操作可能需要遍历整个有序集,此过程最坏复杂度为 O(N) 时间。

可选的 WITHSCORES 参数决定结果集是单单返回有序集的成员,还是将有序集成员及其 score 值一起返回。

zrevrangebyscore 获取指定 score 范围内的数据(score 降序)
# 和 zrangebyscore 一致
127.0.0.1:6379> zrevrangebyscore key max min [WITHSCORES] [LIMIT offset count]
zincrby 为指定元素的 score 增加上指定的数量
127.0.0.1:6379> zincrby key increment member

为有序集 key 的成员 member 的 score 值加上增量 increment 。

可以通过传递一个负数值 increment ,让 score 减去相应的值,比如 ZINCRBY key -5 member ,就是让 member 的 score 值减去 5 。

当 key 不存在,或 member 不是 key 的成员时, ZINCRBY key increment member 等同于 ZADD key increment member 。

当 key 不是有序集类型时,返回一个错误。

score 值可以是整数值或双精度浮点数。

zrem 删除集合中多个元素
# 移除有序集 key 中的一个或多个成员,不存在的成员将被忽略;
# 当 key 存在但不是有序集类型时,返回一个错误;
127.0.0.1:6379> zrem key member [member ...]
zremrangebyrank 根据索引范围删除元素
127.0.0.1:6379> zremrangebyrank key start stop

移除有序集 key 中,指定排名(rank)区间内的所有成员。

区间分别以下标参数 start 和 stop 指出,包含 start 和 stop 在内。

下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。

你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。

返回结果:

当成功删除时,返回 1;

当 key 不存在或 key 为空时,返回 0;

当 key 不为 zset 时,报错;

zremrangebyscore 根据 score 范围删除元素
# 和 zremrangebyrank 用法一致
127.0.0.1:6379> zremrangebyscore key min max
zcount 统计指定 score 范围内元素的个数
127.0.0.1:6379> zcount key min max

返回有序集 key 中, score 值在 min 和 max 之间(默认包括 score 值等于 min 或 max )的成员的数量

返回值:

当 key 不存在或 key 为空时,返回 0;

当 key 不为 zset 时,报错;

zrank 返回某个元素在集合中的排名(score 升序)
127.0.0.1:6379> zrank key member

排名以 0 为底,也就是说, score 值最小的成员排名为 0 。

**返回值:**member 的排名

当 key 不存在或 member 为空时,返回 null;

当 key 不为 zset 时,报错;

zrevrank 返回某个元素在集合中的排名(score 降序)
# 和 zrank 用法一致
127.0.0.1:6379> zrevrank key member
zscore 返回集合中指定元素的 score
127.0.0.1:6379> zscore key member

返回有序集 key 中,成员 member 的 score 值。

如果 member 元素不是有序集 key 的成员,或 key 不存在,返回 nil 。


2.6.3、数据结构

SortedSet(zset)是 redis 提供的一个非常特别的数据结构,内部使用到了2种数据结构。
1、hash 表
类似于 java 中的 Map<String,score>,key 为集合中的元素,value 为元素对应的 score,可以用来快速定位元素定义的 score,时间复杂度为 O(1)
2、跳表
跳表(skiplist)是一个非常优秀的数据结构,实现简单,插入、删除、查找的复杂度均为 O(logN)。类似 java 中的 ConcurrentSkipListSet,根据 score 的值排序后生成的一个跳表,可以快速按照位置的顺序或者 score 的顺序查询元素。这里我们来看一下跳表的原理:
首先从考虑一个有序表开始:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ge4IrnsJ-1661754275956)(../../image/image-20220829111520964.png)]

从该有序表中搜索元素 < 23, 43, 59 > ,需要比较的次数分别为 < 2, 4, 6 >,总共比较的次数为 2 + 4 + 6 = 12 次。有没有优化的算法吗? 链表是有序的,但不能使用二分查找。类似二叉搜索树,我们把一些节点提取出来,作为索引。得到如下结构:
在这里插入图片描述

这里我们把 < 14, 34, 50, 72 > 提取出来作为一级索引,这样搜索的时候就可以减少比较次数了。我们还可以再从一级索引提取一些元素出来,作为二级索引,变成如下结构:

在这里插入图片描述

这里元素不多,体现不出优势,如果元素足够多,这种索引结构就能体现出优势来了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值