前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis系列:Redis的数据结构

Redis系列:Redis的数据结构

作者头像
栗筝i
发布2022-12-01 21:53:44
3790
发布2022-12-01 21:53:44
举报
文章被收录于专栏:迁移内容迁移内容

Redis 的基本数据类型包括:二进制安全字符串 String、Hashes(哈希)、Lists 列表、Sets 集合 和 Sorted sets 有序集合; Redis 的特殊数据类型还包括:geospatial 地理位置、Bitmap 位存储、HyperLogLogs 基数统计;此外,Redis 在 5.0 版本中还引入了 stream 这个全新的数据类型。 本篇内容包括:Redis 基本数据类型(二进制安全字符串 String、Hashes(哈希)、Lists 列表、Sets 集合 和 Sorted sets 有序集合) 以及 Redis 特殊数据类型(geospatial 地理位置、Bitmap 位存储、HyperLogLogs 基数统计)等内容!


文章目录


一、Redis 基本数据类型

Redis 的基本数据类型包括:二进制安全字符串 String、Hashes(哈希)、Lists 列表、Sets 集合 和 Sorted sets 有序集合;

1、二进制安全字符串 String

二进制安全字符串 String:String 是 Redis 的最基本的数据类型,一个 key 对应一个 value,String 类型是二进制安全的,意思是 Redis 的 String 可以包含任何数据,比如图片或者序列化的对象,一个 Redis 中字符串 value 最多可以是 512M。并且的存储是动态的(意味着可以随时修改它本身的值),每次分配内存时会高出实际字符串的length,这样采用预分配冗余空间方式来减少内存的频繁分配。

使用场景一般是存储简单的键值类型。比如用户信息,登录信息,配置信息等。还有一种用得比较多的是 string 的incr/decr操作,即自减/自增操作。调用它是原子性的,无论调用多少次,都一一计算成功,例如需要增减库存的操作。

使用场景:

  1. 缓存基础数据:例如缓存登录用户的基本的缓存数据,但是建议使用 Hash 缓存
  2. 计数器:浏览量、点击数等。利用 string 的 incr/decr 操作,即自减/自增操作,并且它是原子性的。
  3. 限制请求次数:也是利用 incr 方法,以访问者的 ip 和其他信息作为 key,访问一次增加一次计数,超过次数则返回 false;
  4. 分布式共享 session:因为 Redis 是分布式的独立服务,可以在多个应用之间共享,所以可以用作分布式 Session 等场景;
  5. 分布式锁:SET 命令有个 NX 参数可以实现「key不存在才插入」,可以用它来实现分布式锁。

Redis 中字符串类型常用命令:

代码语言:javascript
复制
SET key value 							# 设置指定key的值
GET key 										# 获取指定key的值
SETEX key seconds value 		# 设置指定key的值,并将 key 的过期时间设为 seconds 秒
SETNX key value 						# 只有在 key 不存在时设置 key 的值
2、哈希 Hashes

Redis 的 Hash 相当于 Java 的 HashMap,内部结构实现与 HashMap 一致,即数组+链表结构。只是 reHash 方式不一样。分为大 key、小 key、小 key 的 value。

由于 Hash 结构会在单个 Hash 元素在不足一定数量时进行压缩存储,所以可以大量节约内存。这一点在 String 结构里是不存在的。

使用场景:

  • 缓存: 能直观,相比 string 更节省空间,的维护缓存信息,如用户信息,视频信息等;
  • 购物车:类似存储商品信息,大 key 为商家 id,小 key 是商品 id 即 goodsId,value 为该 goodsId 的详细信息。

hash特别适合用于存储对象,常用命令:

代码语言:javascript
复制
HSET key field value 				# 将哈希表 key 中的字段 field 的值设为 value
HGET key field 							# 获取存储在哈希表中指定字段的值
HDEL key field 							# 删除存储在哈希表中的指定字段
HKEYS key 									# 获取哈希表中所有字段
HVALS key 									# 获取哈希表中所有值
HGETALL key 								# 获取在哈希表中指定 key 的所有字段和值
3、列表 Lists

Lists 列表,它是简单的字符串列表,按照插入顺序排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边),它的底层实际上是个链表( Redis 用双端链表实现 List)。每个链表的节点由一个 listNode 结构来表示,每个节点都有指向前置节点和后置节点的指针,同时表头节点的前置和后置节点都指向 NULL。列表有两个特点:有序、可以重复。

使用场景:

  • 消息队列:消息队列在存取消息时,必须要满足三个需求,分别是消息保序、处理重复的消息和保证消息可靠性。Redis 的 List 和 Stream 两种数据类型,就可以满足消息队列的这三个需求;
  • 最新消息排队功能:与消息队列类似。

Redis 列表是简单的字符串列表,按照插入顺序排序,常用命令:

代码语言:javascript
复制
LPUSH key value1 [value2] 	# 将一个或多个值插入到列表头部
LRANGE key start stop 			# 获取列表指定范围内的元素
RPOP key 										# 移除并获取列表最后一个元素
LLEN key 										# 获取列表长度
BRPOP key1 [key2 ] timeout 	# 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超 时或发现可弹出元素为止
4、集合 Sets

Set 类型是一个无序并唯一的键值集合,它的存储顺序不会按照插入的先后顺序进行存储。Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。相对于列表,集合也有两个特点:无序、不可重复

一个集合最多可以存储 2^32-1 个元素。概念和数学中个的集合基本类似,可以交集,并集,差集等等,所以 Set 类型除了支持集合内的增删改查,同时还支持多个集合取交集、并集、差集。

使用场景:

  • 点赞、踩、收藏:Set 类型可以保证一个用户只能点一个赞;
  • 共同关注、标签:Set 类型支持交集运算,所以可以用来计算共同关注的好友、公众号等;
  • 抽奖活动:存储某活动中中奖的用户名 ,Set 类型因为有去重功能,可以保证同一个用户不会中奖两次。

Redis set 是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据,常用命令:

代码语言:javascript
复制
SADD key member1 [member2] 	# 向集合添加一个或多个成员
SMEMBERS key 								# 返回集合中的所有成员
SCARD key 									# 获取集合的成员数
SINTER key1 [key2] 					# 返回给定所有集合的交集
SUNION key1 [key2] 					# 返回所有给定集合的并集
SDIFF key1 [key2] 					# 返回给定所有集合的差集
SREM key member1 [member2] 	# 移除集合中一个或多个成员
5、有序集合 Zset(Sorted sets)

Zset 类型(有序集合类型)相比于 Set 类型多了一个排序属性 score(分值),对于有序集合 ZSet 来说,每个存储元素相当于有两个值组成的,一个是有序结合的元素值,一个是排序值。

有序集合保留了集合不能有重复成员的特性(分值可以重复),但不同的是,有序集合中的元素可以排序。

使用场景:

  • 排行榜:有序集合比较典型的使用场景就是排行榜。例如学生成绩的排名榜、游戏积分排行榜、视频播放排名、电商系统中商品的销量排名,网站也可以按照用户关注数,更新时间,字数等打分,做排行等;
  • 电话、姓名排序:使用有序集合的 ZRANGEBYLEXZREVRANGEBYLEX 可以帮助我们实现电话号码或姓名的排序。

Zset 常用命令:

代码语言:javascript
复制
ZADD key score1 member1 [score2 member2] 	# 向有序集合添加一个或多个成员,或者更新已存在成员的 分数
ZRANGE key start stop [WITHSCORES] 				# 通过索引区间返回有序集合中指定区间内的成员
ZINCRBY key increment member 							# 有序集合中对指定成员的分数加上增量 increment
ZREM key member [member …] 								# 移除有序集合中的一个或多个成员

Ps:Redis中的通用命令(针对key进行操作的相关命令):

代码语言:javascript
复制
KEYS pattern 															# 查找所有符合给定模式( pattern)的 key
EXISTS key							 									# 检查给定 key 是否存在
TYPE key 																	# 返回 key 所储存的值的类型
TTL key 																	# 返回给定 key 的剩余生存时间(TTL, time to live),以秒为单位
DEL key 																	# 该命令用于在 key 存在是删除 key

二、Redis 特殊数据类型

Redis 的特殊数据类型还包括:geospatial 地理位置、Bitmap 位存储、HyperLogLogs 基数统计;此外,Redis 在 5.0 版本中还引入了 stream 这个全新的数据类型。

1、位存储 Bitmap

Bitmap,即位图,是一串连续的二进制数组(0和1),可以通过偏移量(offset)定位元素。BitMap通过最小的单位bit来进行0|1的设置,表示某个元素的值或者状态,时间复杂度为O(1)

Bitmap 类型非常适合二值状态统计的场景,这里的二值状态就是指集合元素的取值就只有 0 和 1 两种,在记录海量数据时,Bitmap 能够有效地节省内存空间。

使用场景:

  • 签到统计:我们把每天的日期作为 Bitmap 的 key,userId 作为 offset,若是打卡则将 offset 位置的 bit 设置成 1。key 对应的集合的每个 bit 位的数据则是一个用户在该日期的打卡记录;
  • 连续签到用户总数:一共有 7 个这样的 Bitmap,如果我们能对这 7 个 Bitmap 的对应的 bit 位做 『与』运算。同样的 UserID offset 都是一样的,当一个 userID 在 7 个 Bitmap 对应对应的 offset 位置的 bit = 1 就说明该用户 7 天连续打卡;
  • 签到登陆态::Bitmap 提供了 GETBIT、SETBIT 操作,通过一个偏移值 offset 对 bit 数组的 offset 位置的 bit 位进行读写操作,需要注意的是 offset 从 0 开始。

Bitmap 的常用命令:

代码语言:javascript
复制
setbit <key> <offset> <value>		# 设置Bitmaps中某个偏移量的值(0或1)
getbit													# 获取Bitmaps中某个偏移量的值
bitcount <key> [start end] 			# 统计字符串从start字节到end字节比特值为1的数量
2、基数统计 HyperLogLogs

Redis HyperLogLog 是 Redis 2.8.9 版本新增的数据类型,是一种用于「统计基数」的数据集合类型,基数统计就是指统计一个集合中不重复的元素个数。但要注意,HyperLogLog 是统计规则是基于概率完成的,不是非常准确,标准误算率是 0.81%。

所以,简单来说 HyperLogLog 提供不精确的去重计数。

HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的内存空间总是固定的、并且是很小的。

在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数,和元素越多就越耗费内存的 Set 和 Hash 类型相比,HyperLogLog 就非常节省空间。

使用场景:

  • 百万级网页 UV 计数: 在统计 UV 时,你可以用 PFADD 命令(用于向 HyperLogLog 中添加新元素)把访问页面的每个用户都添加到 HyperLogLog 中。 接下来,就可以用 PFCOUNT 命令直接获得 page1 的 UV 值了,这个命令的作用就是返回 HyperLogLog 的统计结果。 不过,有一点需要你注意一下,HyperLogLog 的统计规则是基于概率完成的,所以它给出的统计结果是有一定误差的,标准误算率是 0.81%。
代码语言:javascript
复制
PFADD key element [element ...] 							# 添加指定元素到 HyperLogLog 中。
PFCOUNT key [key ...] 												# 返回给定 HyperLogLog 的基数估算值。
PFMERGE destkey sourcekey [sourcekey ...] 		# 将多个 HyperLogLog 合并为一个 HyperLogLog
3、地理位置 geospatial

Redis GEO 是 Redis 3.2 版本新增的数据类型,主要用于存储地理位置信息,并对存储的信息进行操作。

在日常生活中,我们越来越依赖搜索“附近的餐馆”、在打车软件上叫车,这些都离不开基于位置信息服务(Location-Based Service,LBS)的应用。LBS 应用访问的数据是和人或物关联的一组经纬度信息,而且要能查询相邻的经纬度范围,GEO 就非常适合应用在 LBS 服务的场景中。

使用场景:

  • 滴滴叫车:假设车辆 ID 是 33,经纬度位置是(116.034579,39.030452),我们可以用一个 GEO 集合保存所有车辆的经纬度,集合 key 是 cars:locations。 当用户想要寻找自己附近的网约车时,LBS 应用就可以使用 GEORADIUS 命令。
代码语言:javascript
复制
geoadd china:city 116.40 39.90 beijing       # 添加城市经纬度及名称
geopos china:city beijing                # 返回城市的经度和纬度
geodist china:city beijing shanghai km       # 返回两个元素间的直线距离(单位为km)
georadius china:city 110 30 1000 km        # 以给定的经纬度(110,30)为中心,找到某一半经(1000km)的元素
1)georadius china:city 110 30 1000 km withdist 					# 显示到中间距离的位置
2)georadius china:city 110 30 1000 km withcoord 				# 显示他人的定位信息
3)georadius china:city 110 30 1000 km withcoord count 1 # 筛选出指定个数
georadiusbymember china:city beijing 1000km   # 找出位于指定元素的周围的其他元
4、Stream

Redis Stream 是 Redis 5.0 版本新增加的数据类型,Redis 专门为消息队列设计的数据类型。

在 Redis 5.0 Stream 没出来之前,消息队列的实现方式都有着各自的缺陷,例如:

  • 发布订阅模式,不能持久化也就无法可靠的保存消息,并且对于离线重连的客户端不能读取历史消息的缺陷;
  • List 实现消息队列的方式不能重复消费,一个消息消费完就会被删除,而且生产者需要自行实现全局唯一 ID。

基于以上问题,Redis 5.0 便推出了 Stream 类型也是此版本最重要的功能,用于完美地实现消息队列,它支持消息的持久化、支持自动生成全局唯一 ID、支持 ack 确认消息的模式、支持消费组模式等,让消息队列更加的稳定和可靠。

使用场景:主要就是消息队列。

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-11-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、Redis 基本数据类型
    • 1、二进制安全字符串 String
      • 2、哈希 Hashes
        • 3、列表 Lists
          • 4、集合 Sets
            • 5、有序集合 Zset(Sorted sets)
            • 二、Redis 特殊数据类型
              • 1、位存储 Bitmap
                • 2、基数统计 HyperLogLogs
                  • 3、地理位置 geospatial
                    • 4、Stream
                    相关产品与服务
                    对象存储
                    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                    http://www.vxiaotou.com