Redis数据类型

2 次阅读 预计阅读时间: 17 分钟


n

一、概述

nnnn

Redis是一个开源的,基于内存的数据结构存储系统,它可以用作数据库、缓存和消息中间件。

nnnn

Redis支持多种类型的数据结构,包括:

nnnn
    n
  1. 字符串(String)
  2. nnnn
  3. 列表(List)
  4. nnnn
  5. 集合(Set)
  6. nnnn
  7. 有序集合(Sorted Set)
  8. nnnn
  9. 哈希表(Hash)
  10. nnnn
  11. Bitmap
  12. nnnn
  13. HyperLogLog
  14. nnnn
  15. 地理空间索引(Geo)
  16. nnnn
  17. Streams。
  18. n
nnnn

二、字符串 String

nnnn

1. String 类型简介

nnnn

字符串Strings是Redis最基本的数据类型,它是二进制安全的。一个Redis字符串可以包含任何类型的数据,比如jpg图片或者序列化的对象。一个字符串类型的值最大能存储512MB。

nnnn

2. String 类型的基本用法

nnnn
SET mykey "Hello"  -- 设置键值nGET mykey  -- 获取键值nDEL mykey  -- 删除键值nAPPEND mykey " World"  -- 追加值到现有的键值nSETEX mykey 10 "Hello"  -- 设置键值,并设置键的过期时间(例如,10秒)nMSET key1 "Hello" key2 "World"  -- 批量设置键值nMGET key1 key2  -- 批量获取键值nINCR mycounter  -- 将键值递增1nDECR mycounter  -- 将键值递减1nINCRBY mycounter 10  -- 将键值按给定数值递增(例如,递增10)nDECRBY mycounter 10  -- 将键值按给定数值递减(例如,递减10)
nnnn

3. String 类型的实现原理

nnnn

Redis的字符串类型的值是动态字符串SDS,可以修改的字符串长度。内部结构实现类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配。当字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多分配1M的空间。需要注意的是字符串最大长度为512M。

nnnn

4. String 类型的应用场景

nnnn

字符串是最常用的数据类型,常见的使用场景有:

nnnn
    n
  • 缓存:将查询结果缓存到字符串中,下次查询直接从Redis获取,提高系统性能。
  • nnnn
  • 计数器:Redis的字符串可以实现原子操作,常用于记录网页访问次数等计数功能。
  • nnnn
  • 分布式锁:利用Redis的SETNX命令实现分布式锁。
  • nnnn
  • 数据共享:可以将数据以字符串形式存储在Redis中,实现多个应用之间的数据共享。
  • n
nnnn

5. 简单字符串SDS

nnnn

SDS是Redis的默认字符串表示,它是Redis的基础数据结构,用于构建更复杂的数据结构如列表、哈希表等。SDS相比于C语言的字符串,提供了更高的效率和灵活性。

nnnn

SDS的数据结构包含三部分:

nnnn
    n
  1. len:表示SDS的长度,即字符串的实际长度。
  2. nnnn
  3. free:表示SDS未使用的空间长度。
  4. nnnn
  5. buf[]:字节数组,用于存储实际的字符串数据,这个数组的长度是len+free+1,多出来的1是为了存储字符串的结束符'\0'。
  6. n
nnnn

String的底层实现原理

nnnn

在Redis中,String类型的值就是一个SDS。当我们对String进行操作时,实际上就是在对SDS进行操作。

nnnn
    n
  1. 当我们向String中添加数据时,Redis会先检查SDS的free是否足够,如果足够,就直接在buf中添加数据;如果不足,就需要对SDS进行扩容,扩容的策略是:如果SDS的长度小于1MB,那么扩容的长度就是当前长度的2倍;如果SDS的长度大于等于1MB,那么扩容的长度就是增加1MB。
  2. nnnn
  3. 当我们从String中删除数据时,Redis并不会立即缩小SDS的空间,而是通过增加free的值来表示删除了数据。这是因为,如果频繁地进行内存的分配和释放,会导致内存碎片化,从而影响性能。当SDS的空间真的不够用时,Redis会自动进行内存的整理。
  4. nnnn
  5. 当我们查询String的长度时,Redis可以直接返回SDS的len,这是一个O(1)的操作,非常快。
  6. n
nnnn

三、列表 List

nnnn

1. List 简介

nnnn

Redis的List数据类型是一个由字符串组成的有序列表。列表中的每个字符串都被分配了一个新的索引,这个索引表示了这个字符串在列表中的位置。索引是零基的,这意味着第一个元素的索引是0,第二个元素的索引是1,以此类推。Redis的列表是双向的,这意味着你可以在列表的两端添加或删除元素。

nnnn

2. List 基本用法

nnnn
LPUSH mylist "World"-- 在列表的左侧添加一个或多个值nRPUSH mylist "Hello"-- 在列表的右侧添加一个或多个值nLRANGE mylist 0 -1-- 获取列表中的所有元素nLINDEX mylist 0-- 获取列表中指定位置的元素nLPOP mylist-- 移除并返回列表的第一个元素nRPOP mylist-- 移除并返回列表的最后一个元素nLLEN mylist-- 返回列表的长度
nnnn

3. Lists 实现原理

nnnn

Redis的List数据类型是通过双向链表实现的,这使得在列表的头部和尾部插入或删除元素的操作非常高效。然而,当你需要访问或者修改列表中间的元素时,性能就会下降,因为需要从头部或尾部开始遍历列表。

nnnn

4. List 的应用场景

nnnn

由于Redis的List数据类型提供了在列表两端进行操作的能力,因此它非常适合用于实现队列和栈,这两种数据结构在许多实际应用中都非常有用。

nnnn

例如,你可以使用Redis的List数据类型来实现一个消息队列,其中生产者将消息添加到列表的一端,消费者则从另一端取出消息。

nnnn

四、集合 Set

nnnn

1. Set 简介

nnnn

Redis的Set是字符串的无序集合。Set是通过哈希表实现的,所以添加、删除、查找的复杂度都是O(1)。Set中最大的成员数为 2^32 - 1 (大约40亿)。

nnnn

2. Set 基本用法

nnnn
SADD myset "Hello"-- 向集合添加一个或多个成员nSREM myset "Hello"-- 移除集合中一个或多个成员nSISMEMBER myset "Hello"-- 判断成员元素是否是集合的成员nSMEMBERS myset-- 返回集合中的所有成员nSCARD myset-- 返回集合的成员数nSUNION set1 set2-- 返回两个集合的并集nSINTER set1 set2-- 返回两个集合的交集nSDIFF set1 set2-- 返回两个集合的差集
nnnn

3. Set 实现原理

nnnn

Redis的SET数据类型是通过哈希表实现的,这使得添加、删除和查找等操作的时间复杂度都是O(1)。这种数据结构的优点是操作速度快,但是缺点是占用的内存比较大。

nnnn

4. Set 应用场景

nnnn
    n
  1. 社交网络中的好友关系、粉丝关系:例如,求两个人的共同好友,第一个人关注的人中有多少是也被第二个人关注了,已知两个人,求他们共同关注的人。
  2. nnnn
  3. 利用集合保存用户的属性标签,方便快速判断用户是否具有某个属性标签。
  4. nnnn
  5. 利用集合的交集、并集、差集操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。
  6. n
nnnn

五、有序集合 Sorted Set

nnnn

1. Sorted Set 简介

nnnn

Redis的Sorted SET是SET的升级版,它在SET的基础上增加了一个权重参数score,使得集合中的元素能够按score进行有序排列。在Sorted SET中,元素是唯一的,但score可以重复。

nnnn

2. Sorted Set 基本用法

nnnn
ZADD myzset 1 "one"-- 向有序集合添加一个或多个成员,或者更新已存在成员的分数nZSCORE myzset "one"-- 返回有序集中,成员的分数值nZRANK myzset "one"-- 返回有序集合中指定成员的索引nZRANGE myzset 0 -1-- 通过索引区间返回有序集合成指定区间内的成员nZREM myzset "one"-- 移除有序集合中的一个或多个成员nZCARD myzset-- 获取有序集合的成员数nZCOUNT myzset min max-- 计算在有序集合中指定区间分数的成员数
nnnn

3. Sorted Set 实现原理

nnnn

Redis的Sorted SET数据类型是通过跳跃列表(Skip List)和哈希表(Hash Table)实现的。哈希表用于支持O(1)复杂度的元素查找,而跳跃列表则用于支持元素的有序排列和区间查找。

nnnn
    n
  • 跳跃列表:跳跃列表是一种可以进行快速查找的数据结构,它通过在每个节点中维护多个指向其他节点的指针,从而使得查找的时间复杂度降低到了O(logN)。在Redis的有序集合中,跳跃列表主要用于元素的排序和区间查询。
  • nnnn
  • 哈希表:哈希表是一种可以进行快速插入和查找的数据结构,它通过一个哈希函数将元素映射到一个大的空间中,从而使得插入和查找的时间复杂度降低到了O(1)。在Redis的有序集合中,哈希表主要用于元素的快速查找和删除。
  • n
nnnn

当我们向有序集合中添加一个元素时,Redis会同时向跳跃列表和哈希表中添加这个元素。其中,跳跃列表按照元素的score进行排序,而哈希表则按照元素的值进行映射。

nnnn

当我们查询一个元素时,如果是按照score进行区间查询,Redis会使用跳跃列表;如果是按照元素的值进行查询,Redis会使用哈希表。

nnnn

当我们删除一个元素时,Redis会同时从跳跃列表和哈希表中删除这个元素。

nnnn

通过这种方式,Redis的有序集合既可以进行快速的插入和删除,也可以进行快速的排序和区间查询,从而满足了各种不同的需求。

nnnn

4. Sorted Set 应用场景

nnnn
    n
  1. 排行榜应用:Sorted Set可以非常方便地实现排行榜,比如游戏的排行榜,网站的点击排行等。
  2. nnnn
  3. 时间线和日志:Sorted Set的score可以用作时间戳,value可以用作日志内容。
  4. nnnn
  5. 计数器:Sorted Set可以用来做各种计数器,比如微博的关注者数等。
  6. n
nnnn

六、哈希表 Hash

nnnn

1. Hash 简介

nnnn

Redis的哈希类型是一个由键值对组成的无序散列表。哈希类型适合用于存储对象,其中键名对应字段名,键值对应字段值。

nnnn

2. Hash 的基本用法

nnnn
HSET myhash field1 "Hello"-- 设置哈希表中一个字段的值nHGET myhash field1-- 获取存储在哈希表中指定字段的值nHGETALL myhash-- 获取在哈希表中指定的所有字段和值nHDEL myhash field1-- 删除一个或多个哈希表字段nHEXISTS myhash field1-- 查看哈希表中,指定的字段是否存在nHLEN myhash-- 获取哈希表中字段的数量nHKEYS myhash-- 获取所有哈希表中的字段nHVALS myhash-- 获取哈希表中所有值
nnnn

3. Hash 的实现原理

nnnn

Redis的Hash数据类型是通过哈希表实现的,这使得添加、删除和查找等操作的时间复杂度都是O(1)。这种数据结构的优点是操作速度快,但是缺点是占用的内存比较大。

nnnn

4. Hash 的应用场景

nnnn
    n
  1. 存储对象:哈希类型非常适合用于存储对象,比如用户的信息,商品的信息等。
  2. nnnn
  3. 缓存系统:哈希类型可以用来做缓存,提高系统的性能。
  4. nnnn
  5. 计数器:哈希类型也可以用来做各种计数器,比如网站的点击量等。
  6. n
nnnn

七、Bitmap

nnnn

1. Bitmap 简介

nnnn

Redis并没有专门的Bitmap数据类型,但是它提供了一系列的位操作命令,使得我们可以把字符串当作Bitmap来使用。Bitmaps是一种特殊的数组,其中的每个元素只能存储0和1。例如,一个8位的Bitmap可以存储从0到255的整数。

nnnn

2. Bitmap 基本用法

nnnn
SETBIT mykey 7 1  -- 设置或清除指定偏移量上的位(bit)nGETBIT mykey 7  -- 获取指定偏移量上的位(bit)nBITCOUNT mykey  -- 计算给定字符串中被设置为 1 的位的数量nBITPOS mykey 1  -- 返回第一个值为 1 或 0 的二进制位的位置
nnnn

3. Bitmap 实现原理

nnnn

Redis的Bitmaps实际上就是字符串,它通过位操作命令来实现Bitmaps的功能。这种数据结构的优点是存储效率高,可以用来存储大量的二进制数据。

nnnn

4. Bitmap 应用场景

nnnn
    n
  1. 用户行为分析:例如,可以用Bitmaps来记录用户的登录情况,每天用一个Bitmap,如果用户登录了,就把用户ID对应的位设置为1。
  2. nnnn
  3. 统计在线用户数:可以用Bitmaps来记录每个用户的在线状态,然后用BITCOUNT命令就可以快速统计在线用户数。
  4. nnnn
  5. 实现一些特殊的计数器:例如,可以用一个Bitmap来记录用户的签到情况,然后用BITCOUNT命令就可以快速统计用户的签到天数。
  6. n
nnnn

八、其他

nnnn

1. HyperLogLog

nnnn

HyperLogLog是一种用于解决基数统计的算法,Redis从2.8.9版本开始增加了对HyperLogLog的支持。基数统计就是统计不同元素的数量。HyperLogLog的优点是,即使对数亿级别的数据进行基数统计,也只需要使用12KB的内存空间。

nnnn
PFADD mykey element1 element2-- 添加指定元素到 HyperLogLog 中nPFCOUNT mykey-- 返回给定 HyperLogLog 的基数估算值nPFMERGE destkey sourcekey1 [sourcekey2]-- 将多个 HyperLogLog 合并为一个 HyperLogLog
nnnn

2. 地理空间索引(Geo)

nnnn

Redis的地理空间索引功能是通过zset实现的,它可以存储经度、纬度、名称,然后对这些信息进行各种地理空间操作。

nnnn
GEOADD mykey longitude latitude member-- 将给定的空间元素(纬度、经度、名字)添加到指定的键里面nGEODIST mykey member1 member2-- 返回两个给定位置之间的距离nGEOPOS mykey member-- 返回指定位置元素的位置(经度和纬度)nGEORADIUS mykey longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]-- 查询指定半径内的位置元素
nnnn

3. Streams

nnnn

Redis 5.0引入了新的数据类型Streams,它是一个持久化的日志系统,每个条目都包含一个ID和一组键值对。Streams主要用于消息队列的场景,比如Kafka

nnnn
XADD mykey ID field1 value1 [field2 value2]-- 在stream里添加条目nXRANGE mykey start end [COUNT count]-- 返回ID在指定范围内的条目nXREAD [COUNT count] [BLOCK milliseconds] STREAMS key1 key2-- 从stream里读取条目
n
最后更新于 2024-05-22