一、十大类型概述

  • 首先,我们要知道此处的数据类型指的是 value 的类型,Rediskey 都是字符串类型
  • 我们通过一张图,先大致了解一下这些数据结构的样子

1.1 String 类型

  • StringRedis 中最基本的数据类型,一个 key 对应一个 value 【字符串】
  • String 类型是二进制安全的,支持序列化,可以包含任何数据 【例如:jpg图片、序列化的对象等】
  • 一个 Redis 中字符串 value 最多可以是512M

1.2 List 类型

  • Redis 列表是简单的字符串列表,按照插入顺序排序,可以从两侧插入【列表】
  • 底层是一个双端链表,可以插入 2^32 - 1 个元素【每个列表可以超过 40亿 个元素】

1.3 Hash 类型

  • Redis hash 是一个 String 类型的 field 字段 和 value 值的映射表, hash 特别适合用于存储对象【哈希表】
  • Redis 中每个 hash 可以存储 2^32 - 1 个键值对【40多亿】

1.4 Set 类型

  • RedisSetString 类型的无序集合,集合成员唯一,编码可以为 intset 或者 hashtable 【Set集合】
  • RedisSet 集合是通过哈希表实现的,所以添加、删除、查找的复杂度都是 O(1)
  • Set 集合中最大成员数为 2^32 - 1 个【40多亿】

1.5 ZSet 类型

  • RedisZSetSet 一样,也是 String 类型元素的集合,且不允许出现重复的元素【SortedSet 集合】
  • ZSet 集合也是通过哈希表实现的,所以添加、删除、查找的复杂度都是O(1),最大成员数也是 2^32 - 1
  • Set 集合不同之处是 ZSet 集合的每个元素都会关联一个 double 类型的分数
  • Redis 会通过这个分数为集合中的元素进行从小到大的排序
  • ZSet 集合成员是唯一的,但是 Score 分数可以相同

1.6 GEO 类型

  • RedisGEO 主要用于存储地里位置信息,并对存储的信息进行操作,主要为以下几种操作:【地理空间】
  • 添加地理位置的坐标
  • 获取地理位置的坐标
  • 计算两个位置之间的距离
  • 根据用户给定的经纬度坐标来获取指定范围内的地理位置集合

1.7 HyperLogLog 类型

  • HyperLogLog 是用来做基数统计的算法,优点在于输入元素的数量或体积很大时,计算基数所需的空间总是固定且很小 【基数统计】
  • 基数:就是去重后元素出现的个数
  • 之所以基数统计占用的空间很小,是因为它不记录元素本身,只是统计去重后元素的个数
  • Redis 中 每个 HyperLogLog 键只需要花费 12KB内存,就可以计算接近 2^64 个不同元素的基数,这和计算基数时元素越多耗费内存越多的集合形成鲜明对比
  • 但是,因为 HyperLogLog 只会根据输入元素计算基数,而不会存储输入元素本身,所以 HyperLogLog 不能像集合那样返回输入的各个元素

1.8 bitmap 类型

  • 由 0 和 1 状态表示的二进制位的 bit 数组 【位图】

新版本redis的数据类型 redis7种数据类型_redis

1.9 bitfield 类型

  • 通过 bitfield 命令可以一次性操作多个比特域(连续的多个比特位),它会执行一系列操作并返回一个响应数组,这个数组中的元素对应参数列表中的相应操作的执行结果 【位域】
  • 总结,通过 bitfield 命令可以为我们一次性对多个比特域进行操作

1.10 Stream 类型

  • RedisStream 类型是 Redis5.0 版本新增加的数据结构
  • RedisStream 主要用于消息队列(Message Queue),Redis 本身有一个 发布订阅(pub/sub)来实现消息队列的功能
  • 但是它有缺点:
  • 无法实现消息持久化
  • 如果出现网络断开、Redis 宕机等,消息就会被丢弃
  • 尽管 Redis 的发布、订阅可以分发消息,但是无法记录历史消息
  • RedisStream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每个客户端的访问位置,保证消息不丢失

我们可以通过 英文/中文 官网去查询Redis常见数据类型的操作命令:

二、Redis对 key 的操作

新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_02

🌔 1、设置、获取、遍历全部 key

  • 通过 set k1 v1 可以创建一个名为 k1key,它的 valuev1
  • 通过get k1 可以获取名为 k1key 对应的 value
  • 通过 keys * 可以打印出当前数据库中的所有 key

新版本redis的数据类型 redis7种数据类型_学习_03

🌔 2、判断某个 key 是否存在,判断属于什么类型

  • 通过 exists key 可以判断我们指定的 key 是否存在
  • 通过 type key 可以查看我们指定的 key 属于哪种类型

新版本redis的数据类型 redis7种数据类型_学习_04

🌔 3、删除我们的key

  • 两种方式都可以实现删除的效果
  • 通过 del key 可以直接删除我们的 key 数据 【如果当前要删除的是超大文件,就可能导致出现线程阻塞的现象】
  • 通过 unlink key 可以实现非阻塞删除,仅仅将 keyskeyspace 元数据中删除,真正的删除会在后续异步中操作

新版本redis的数据类型 redis7种数据类型_redis_05

🌔 4、为我们的key设置过期时间,查看key还有多久过期

新版本redis的数据类型 redis7种数据类型_数据库_06

  • 通过ttl key 可以查看我们的key还有多少秒过期 【-1代表永不过期,-2代表已经过期】
  • 通过 expire key 秒钟 可以为我们的key设置过期时间

新版本redis的数据类型 redis7种数据类型_redis_07

🌔 5、切换数据库、查看当前数据库中key的数量、移动key所属数据库


  • 通过 sellect dbindex 可以切换数据库 【默认数据库为0,总共有16个数据库,所以dbindex的取值范围为0-15】
  • 新版本redis的数据类型 redis7种数据类型_Redis_08


  • 通过dbsize 可以查看当前数据库中 key 的个数
  • 新版本redis的数据类型 redis7种数据类型_学习_09


  • 通过 move key dbindex 可以将当前数据库中的 key 移动到指定索引的数据库中
  • 新版本redis的数据类型 redis7种数据类型_数据库_10

🌔 6、清空

  • 通过 flushdb 可以清空当前库中所有的 key
  • 通过 flushall 可以清空所有库(16个库)中所有的 key

三、各种数据类型相关命令

  • 对于命令是不区分大小写的,但是 key 是区分大小写的
  • 我们可以通过 help @数据类型 指令查看相关帮助文档

3.1 String 字符串

新版本redis的数据类型 redis7种数据类型_学习_11


🌔 1、最常用的指令

  • 通过 set key value 指令可以创建一个 key
  • 完整指令:set key value [NX|XX] [GET] [EX seconds|PX milliseconds|EXAT unix-time-seconds|PXAT unix-time-milliseconds|KEEPTTL]
  • NX: 代表键不存在的时候设置键值 【防止失误覆盖】
  • XX:键存在的时候设置键值
  • GET:返回指定键原来的值,若原来键不存在就返回 nil
  • EX seconds:代表以秒为单位设置过期时间
  • PX milliseconds:以毫秒为单位设置过期时间
  • EXAT timestamp:设置以秒为单位的 UNIX 时间戳所对应的时间为过期时间
  • PXAT milliseconds-timestamp:设置以毫秒为单位的UNIX时间戳所对应的时间为过期时间
  • 那么如何获得设置指定的Key过期的Unix时间呢(单位为秒)【在Java中我们可以通过下面这段代码完成】
    System.out.println(Long.toString(System.currentTimeMillis() / 1000L));
  • KEEPTTL:保留设置前指定键的生存时间
  • 设置成功返回 OK, 返回 nil 为未执行 set 命令 或 使用了get参数但键原来不存在
  • 通过 get key 指令可以获取 key 对应的 value

nx、xx 参数测试

新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_12

ex 参数测试 【其他几个过期时间用法同理】

新版本redis的数据类型 redis7种数据类型_Redis_13

  • 重点说明一下 keepttl 参数的使用:可以保证键的生存时间不变,用于解决过期时间冲突问题
  • 当我们在创建 k1 键时设置了过期时间,但是我们修改 k1 键之后,过期时间就会变为改变
  • 我们只需要在修改 k1 键的时候添加 keepttl 选项,就会自动使用剩余的过期时间设置为新的过期时间

新版本redis的数据类型 redis7种数据类型_学习_14

🌔 2、同时设置/获取多个键值


  • 通过 mset key value [key value ...] 指令可以同时设置多个 key
  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_15


  • 通过mget key [key ...] 指令可以同时获取多个 key 对应的 value
  • 新版本redis的数据类型 redis7种数据类型_Redis_16


  • 通过 msetnx key value [key value ...] 指令可以同时设置多个指定 key 不存在的键
  • 新版本redis的数据类型 redis7种数据类型_数据库_17

🌔 3、获取指定区间范围内的值


  • 通过 getrange key idx1 idx2 指令可以获取 key 键对应索引为 idx1idx2 范围 的 value 部分值
  • 新版本redis的数据类型 redis7种数据类型_redis_18


  • 通过 setrange key idx value 指令可以将 keyidx 索引开始用 value 覆盖对应位置的元素
  • 新版本redis的数据类型 redis7种数据类型_redis_19

🌔 4、数值运算 【前提条件 value 是数字】

  • 通过 incr key 指令可以将 key 对应的 value 加一
  • 通过 decr key 指令可以将 key 对应的 value 减一
  • 通过 incrby key increment 指令可以将 key 对应的 valueincrement
  • 通过 decrby key decrement 指令可以将 key 对应的 valuedecrement

新版本redis的数据类型 redis7种数据类型_redis_20

🌔 5、获取字符串长度和内容追加

  • 通过 strlen key 可以获取 key 对应的 value 的长度
  • 通过 append key value 可以在 key 对应的 value 的末尾追加上指定的 value 的内容

🌔 6、分布式锁


  • 通过 setnx key value 指令可以在当 key 不存在的情况下为我们创建键,对应值为 value
  • 新版本redis的数据类型 redis7种数据类型_Redis_21


  • 通过 setex key 秒值 value 指令可以在设置键的同时指定过期时间 【就是不用先set然后再expire了】
  • 新版本redis的数据类型 redis7种数据类型_数据库_22

🌔 7、getset 指令

  • 通过 getset key value 指令可以将 key 对应的值设置为 value,并返回 key 对应的原来的值

🌔 8、应用场景


  • 可以用于短视频点赞
  • 新版本redis的数据类型 redis7种数据类型_数据库_23


  • 还可以用于是否喜欢一个文章的点亮 【incr key】
  • 新版本redis的数据类型 redis7种数据类型_Redis_24

3.2 List 列表

  • 列表属于一种 单 keyvalue 的数据结构
  • 属于一种双端链表的结构,可以存储40多亿个元素,主要功能为 push/pop,一般用在栈、队列、消息队列等场景
  • 两侧都可以进行插入和删除操作
  • 如果添加元素时键不存在,就创建新的链表
  • 如果添加元素时键已存在,就向列表中添加元素
  • 如果值全部移除,那么对应的键也就消失了

新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_25


🌔 1、添加 遍历元素

  • 通过 lpush list value [value ...] 指令可以创建一个 list 类型的keyvalue是对应的值,从左侧进入队列【可以创建一个或多个value
  • 通过 roush list value[value ...] 指令可以创建一个 list 类型的keyvalue是对应的值,从右侧进入队列
  • 通过 lrange list start end 指令可以从左到右遍历 start-end 索引内的所有元素并输出 【0 -1 代表所有】

新版本redis的数据类型 redis7种数据类型_学习_26

🌔 2、删除列表中的元素

  • 通过 lpop list 指令可以从首部删除 list 的一个元素
  • 通过 rpop list 指令可以从尾部删除 list 的一个元素

新版本redis的数据类型 redis7种数据类型_学习_27

🌔 3、获取元素和获取元素的个数

  • 通过 lindex list index 指令可以获取 list 列表,index 索引处的元素值 【index的排序可以理解为从上到下、从左到右】
  • 通过 llen list 指令可以获取 list 列表中元素的个数

🌔 4、批量删除和截取

  • 通过lrem key count value 指令可以删除 count 个值为 value 的元素,返回值为实际删除的数量 【如果count为零,就代表删除所有值】

新版本redis的数据类型 redis7种数据类型_Redis_28

  • 通过 ltrim list start end 指令可以截取list列表 start-end 的元素值,范围外的元素都会被删除

🌔 5、移动、修改、插入元素


  • 通过 通过rpoplpush list1 list2 指令可以从 list1 列表的尾部弹出一个元素,然后从 list2 列表的首部进入
  • 新版本redis的数据类型 redis7种数据类型_数据库_29


  • 通过lset list index value 指令可以修改 list 列表 index 索引位置的元素值
  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_30


  • 通过 linsert list before/after value value2 指令可以在 listvalue 前或后插入元素元素 value2valuelist 中已经存在的元素】
  • 新版本redis的数据类型 redis7种数据类型_数据库_31

🌔 6、应用场景

  • 可以用于微信公众号订阅

3.3 Hash 哈希


  • 一个key对应一个 value,value是键值对类型又可以对应一个值
  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_32

  • 🌔 1、基本操作
  • 通过 hset hash key value 指令可以创建一个键为 hash的哈希表,这个哈希表的映射为 key -> value
  • 通过 hget hash key 指令可以获取键为 hash 的 key 对应的 value 值
  • 通过 hmset hash1 field1 value1 field2 value2 指令可以创建一个hash键的多组 filed 映射
  • 通过 hmget hash1 field1 field2 指令可以获取该 hash 的多组 field 对应的值

  • 通过 hgetall hash1 指令可以获取 hash1 中所有的 field 与 value 的键值对
  • 新版本redis的数据类型 redis7种数据类型_redis_33


  • 通过 hdel hash1 field1 field2 指令可以删除 hash 中 field1 和 field2 对应的键值对
  • 新版本redis的数据类型 redis7种数据类型_学习_34


  • 通过 hlen hash1 指令可以获取 hash1 中键值对的个数
  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_35


  • 通过 hexists hash1 field 指令可以判断 hash1 中是否存在 field
  • 新版本redis的数据类型 redis7种数据类型_学习_36

🌔 2、算数运算

  • 通过 hincrby hash1 field1 number1 指令可以让 hash1 的 field1 对应的值加上 number1 【整型数】

  • 通过 hincrbyfloat hash2 field2 number2 指令可以让 hash2 的 field2 对应的值加上 number2 【浮点数】
  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_37


  • 通过 hsetnx hash1 field1 value1 指令可以在创建 hash1 的时候判断是否为不存在的键,存在了就不创建了
  • 新版本redis的数据类型 redis7种数据类型_redis_38

  • 通过 hkeys hash1 指令可以获取 hash1 中所有的 field

  • 通过 hvals hash1 指令可以获取 hash1 中所有的 field 对应的 value
  • 新版本redis的数据类型 redis7种数据类型_学习_39

3.4 Set 集合

  • 是一种单值多 value 的数据结构,而且 value 不重复

🌔 1、常用方法

  • 通过 sadd key member [member ...] 指令可以创建一个 key 集合,同时可以创建一个或多个值

  • 通过 smembers key 指令可以遍历 key 集合中的所有元素
  • 新版本redis的数据类型 redis7种数据类型_数据库_40


  • 通过 sismember key member 指令可以判断集合 key 中是否存在 member 元素
  • 新版本redis的数据类型 redis7种数据类型_数据库_41

  • 通过 srem key member [member ...] 指令可以删除 key 集合中的 member 元素

  • 通过 scard key 指令可以获取 key 集合中元素的个数
  • 新版本redis的数据类型 redis7种数据类型_redis_42


  • 通过 srandmember key n 指令可以随机展现 key 集合中的 n 个元素
  • 新版本redis的数据类型 redis7种数据类型_学习_43


  • 通过 spop key n 指令可以弹出 key 集合中的 n 个元素
  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_44


  • 通过 smove key1 key2 member 指令可以将 key1 集合中的 member 元素移除并添加到 key2 集合中
  • 新版本redis的数据类型 redis7种数据类型_Redis_45

🌔 2、集合运算


  • 集合的差集运算(属于前者不属于后者的部分)我们可以通过 sdiff key[key...] 指令完成
  • 新版本redis的数据类型 redis7种数据类型_Redis_46


  • 集合的并集运算,我们可以通过 sunion key [key ...] 指令完成
  • 新版本redis的数据类型 redis7种数据类型_Redis_47

  • 集合的交集运算,我们可以通过 sinter key [key ...] 指令完成
  • 通过 sintercard numkeys key [key ...] [Limit limit] 指令可以返回 numkeys 个 集合交集结果中元素的个数

新版本redis的数据类型 redis7种数据类型_数据库_48


🌔 3、应用场景

(1)微信抽奖小程序

新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_49

需求

实现

1 用户ID,立即参与按钮

sadd key 用户ID

2 显示已经有多少人参与了,上图23208人参加

SCARD key

3 抽奖(从set中任意选取N个中奖人)

SRANDMEMBER key 2 随机抽奖2个人,元素不删除SPOP key 3

(2) 朋友圈点赞查看共同点赞的好友

新版本redis的数据类型 redis7种数据类型_Redis_50

需求

实现

1 新增点赞

sadd pub:msgID 点赞用户ID1 点赞用户ID2

2 取消点赞

srem pub:msgID 点赞用户ID

3 展现所有点赞过的用户

SMEMBERS pub:msgID

4 点赞用户数统计,就是常见的点赞红色数字

scard pub:msgID

5 判断某个朋友是否对楼主点赞过

SISMEMBER pub:msgID 用户ID

(3)QQ推荐可能认识的人

新版本redis的数据类型 redis7种数据类型_Redis_51

3.5 ZSet 有序集合

  • 底层也是 Set 集合,只不过对于每个 value 前添加了 score,为了便于 Redis 对集合内元素排序

新版本redis的数据类型 redis7种数据类型_学习_52

  • 通过 zadd key score member [score member ...] 指令可以向 zset 集合中添加元素
  • 通过 zrange key start stop [withscores] 指令可以遍历输出指定范围的元素,也可以携带上分数【升序】

  • 通过 zrevrange key start stop [withscores] 指令和上面的遍历类似,只不是是逆序输出
  • 新版本redis的数据类型 redis7种数据类型_redis_53

  • 通过 zrangebyscore key min max [withscores] [limit offset count] 指令可以获取指定分数范围内的元素
  • 选项 withscores 代表是否携带分数显示
  • 选项 limit offset count 代表返回符合条件的多少个元素

  • 对于 start 和 stop 代表的是 score,如果在前面带上左半括号意思为不包括(
  • 新版本redis的数据类型 redis7种数据类型_学习_54


  • 通过 zscore key member 指令可以获取 key 集合中 member 元素对应的 score

  • 通过 zcard key 指令可以获取 key 集合中元素的个数
  • 新版本redis的数据类型 redis7种数据类型_redis_55


  • 通过zrem key member 指令可以删除我们 key 集合中的 member 元素与对应的 score
  • 新版本redis的数据类型 redis7种数据类型_数据库_56


  • 通过 zincrby key increment member 指令可以为key集合中的member 元素加上 increment
  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_57


  • 通过 zcount key min max 指令可以获取 key 集合中分数 在 min-max 之间元素的个数
  • 新版本redis的数据类型 redis7种数据类型_数据库_58

  • 通过 zmpop numkeys key [key...] [min | max count] 可以删除numkeys个 key
  • 如果指定了 min 或 max count,就代表删除最大的几个或最小的几个元素
  • 通过 zrank key values 可以获取 key 集合中 value 对应的下标值 【默认是score从小到大排序】
  • 通过 zrevrank key values 和上面的获取索引基本相同,只不过是逆序获取

应用场景:根据商品销售量对商品进行排序显示

  • 思路:定义商品销售排行榜(sorted set集合),key为 goods:sellsort,分数为商品销售数量。

需求

实现

商品编号1001的销量是9,商品编号1002的销量是15

zadd goods:sellsort 9 1001 15 1002

有一个客户又买了2件商品1001,商品编号1001销量加2

zincrby goods:sellsort 2 1001

求商品销量前10名

ZRANGE goods:sellsort 0 9 withscores

新版本redis的数据类型 redis7种数据类型_学习_59

3.6 bitmap 位图

  • 是由 0 和 1 状态表现的二进制位的 bit 数组
  • 用String类型作为底层数据结构实现的一种统计二值状态的数据类型
  • 位图本质是数组,它是基于String数据类型的按位的操作。该数组由多个二进制位组成,每个二进制位都对应一个偏移量(我们称之为一个索引)
  • Bitmap支持的最大位数是232位,它可以极大的节约存储空间,使用512M内存就可以存储多达42.9亿的字节信息(232 = 4294967296)
  • 可以用于签到记录、公告是否被点击过 【状态统计 Y、N】

🌔 基本命令

新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_60

  • 通过 setbit key offset value 指令可以将 key 位图的 offset 索引位置的值设置为 value【索引(偏移量)是从零开始的】

  • 通过 getbit key offset 指令可以获取 key 位图 offset 位置对应的 value
  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_61

  • 通过 strlen key 可以统计key位图所占字节数(8bit为一个字节)【具体使用了多少位看我们设置offset最大使用到了哪里】

  • 通过 bitcount key 指令可以统计 key 位图中有多少个值为1的元素
  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_62


  • 通过bitop 操作 key3 key1 key2 指令可以将位图 key1key2 按位进行指定的操作,并将操作的结果保存到位图 key3
  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_63


  • 新版本redis的数据类型 redis7种数据类型_redis_64

  • 🌔 应用场景
  • 可以统计一个用户一年的登录记录
  • 按年去存储一个用户的签到情况,365 天只需要 365 / 8 ≈ 46 Byte,1000W 用户量一年也只需要 44 MB 就足够了
  • 每天使用1个1亿位的Bitmap约占12MB的内存(10^8/8/1024/1024),10天的Bitmap的内存开销约为120MB,内存压力不算太高
  • 此外,在实际使用时,最好对Bitmap设置过期时间,让Redis自动删除不再需要的签到记录以节省内存开销

3.7 HyperLogLog 基数统计

  • 是去重复统计功能的基数估计算法

  • 基数 是一种数据集,去重复后的真实个数
  • 新版本redis的数据类型 redis7种数据类型_redis_65

  • 基数统计:用于统计一个集合中不重复的元素个数,就是对集合去重后剩余元素的计算

🌔 基本命令

新版本redis的数据类型 redis7种数据类型_数据库_66

新版本redis的数据类型 redis7种数据类型_数据库_67

🌔 应用案例

  • 可以应用在 网站首页亿级 UVRedis 统计方案
  • 什么是 UV ?
  • Unique Visitor(独立访客),一般理解为客户端 IP
  • 可以用于统计某个用户每天搜索不同词条个数

3.8 GEO 地理空间

  • 核心思想就是将球体转换为平面,区块转换为一点,将一维的点块转换为二进制再通过 base 编码
  • 底层是由 ZSet 实现的,所以我们就可以使用一些 ZSet 的方法

🌔 基本命令

  • 我们可以通过下面这个网站 查询某个地址的经纬度
  • 通过 geoadd key longitude latitude member[longitude latitude member..] 指令可以在地理空间 key 中创建一个或多个 member 位置的 longitude 经度、latitude 维度
  • 通过 zrange key start end 指令可以遍历我们指定范围内的位置,但是我们可能会出现中文乱码问题
  • 我们可以通过 redis-cli --raw 指令解决 【在重启客户端的时候添加选项】
  • 通过 geopos key member [member ...] 指令可以获取地理空间key一个或多个位置的经纬度
  • 通过 geohash key member [member...] 指令可以获取地理空间 key 的一个或多个位置特殊编码后的值 【就是将经度和纬度整合成一个特殊的数据】
  • geobash 算法生成的 base32 编码值
  • 通过 geodist key member1 member2 [m|km|ft|mi] 指令可以计算一个地理空间中两个位置的距离
  • m 代表以米为单位、km 代表千米
  • ft 代表英尺、mi 代表英里
  • 通过 georadius key 指定位置经纬度 距离 单位 withdist withcoord count n withhash desc 指令可以在指定位置为中心,查找指定半径范围内所有位置,并显示出他们的经纬度、与中心位置的距离,以距离升序的方式显示出 n 条记录
  • 通过 georadiusbymember key member-name distance unit withdist withcoord count n withhash 也是按半径查找位置,只不过中心点是我们地理空间中已经存在的一个位置

    🌔 应用场景
  • 美团地图位置附近酒店推送
  • 高德地图附近的核酸检查点

3.9 Stream 流

🌔 先介绍一些流相关的概念

  • 该数据类型是在 Redis5.0 版本新增的,属于Redis版的 消息中间件 + 阻塞队列
  • 之前Redis 实现消息队列有两种方式:
  • 第一种是通过 List 列表实现消息队列 【List 实现方式采用的是点对点的模式】
  • 按照插入顺序排序,你可以添加一个元素到列表的头部或尾部
  • 常用作异步队列使用,将需要延后处理的任务结构体序列化成字符串塞进 Redis 的列表,另一个线程从这个列表中轮询数据进行处理
  • 第二种是通过 (Pub/Sub) 实现消息队列
  • 缺点无法实现消息持久化
  • 如果出现网络断开、Redis 宕机等,消息就会被丢弃
  • 没有 Ack 机制来保证数据的可靠性,假设一个消费者都没有,那消息就直接被丢弃了
  • 我们的 Stream 可以实现消息队列,支持消息的持久化、支持自动生成全局唯一ID、支持ACK确认消息的模式,支持消费组模式等,让消息队列更加的稳定和可靠
  • Stream 底层结构和原理说明:

新版本redis的数据类型 redis7种数据类型_学习_68


我们可以看出,一个消息链表,将所有加入的消息都串起来,每个消息都有唯一的ID和对应的内容

对于上面图中的名字解释:

名词

含义

Message Content

消息内容

Consumer group

消费组,通过XGROUP CREATE 命令创建,同一个消费组可以有多个消费者

Last_delivered_id

游标,每个消费组会有个游标 last_delivered_id,任意一个消费者读取了消息都会使游标 last_delivered_id 往前移动。

Consumer

消费者,消费组中的消费者

Pending_ids

消费者会有一个状态变量,用于记录被当前消费已读取但未ack的消息Id,如果客户端没有ack,这个变量里面的消息ID会越来越多,一旦某个消息被ack它就开始减少。这个pending_ids变量在Redis官方被称之为 PEL(Pending Entries List),记录了当前已经被客户端读取的消息,但是还没有 ack (Acknowledge character:确认字符),它用来确保客户端至少消费了消息一次,而不会在网络传输的中途丢失了没处理

🌔 基本操作

(1)队列相关指令

新版本redis的数据类型 redis7种数据类型_学习_69

  • 通过 xadd key * field value [field value ...] 指令可以向 key 流中添加一个或多个 field-value 【不论多少个键值对,添加一次为一个完整的消息】
  • 如果 key 流不存在,就会创建一个 key 队列
  • * 代表服务器自动生成 MessageID,后面顺序跟着一堆业务 key/value 【类似于自增主键】
  • 我们自己设置 ID 的话,一定要确保 当前消息ID比上一个消息的ID大
  • 通过 range key start end count n 指令可以按从小到大遍历出 key 流中的前n条记录
  • start 表示开始值, - 代表最小值
  • end 表示结束值, + 代表最大值
  • count 表示获取多少个值
  • 通过 xrevrange key start end count n 指令和上面的功能类似,只是逆序进行输出
  • 通过 xdel key 序列号 指令可以删除流中指定序列号的信息
  • 通过 xlen key 指令可以获取消息队列的长度
  • 通过 xtrim key maxlen n 指令可以对 key 流进行截取,保留长度为n的最新的消息
  • 通过 xtrim key minid id 指令可以对 key 流进行截取,保留 序列号大于我们指定 id 的消息
  • 通过 xread [count] [block milliseconds] streams key [key...] ID [ID ...] 指令可以读取消息
  • count 代表最多读取多少条消息
  • block 代表是否采用阻塞的方式读取消息,默认不阻塞, milliseconds 设置为0代表永远阻塞

非阻塞:

  • $代表特殊ID,表示以当前Stream已经存储的最大的ID作为最后一个ID,当前Stream中不存在大于当前最大ID的消息,因此此时返回nil
  • 0-0代表从最小的ID开始获取Stream中的消息,当不指定count,将会返回Stream中的所有消息,注意也可以使用0(00/000也都是可以的……)

新版本redis的数据类型 redis7种数据类型_redis_70

阻塞:就是流中没有信息,需要等待信息到达再读取

新版本redis的数据类型 redis7种数据类型_redis_71

(2)消费组相关指令

新版本redis的数据类型 redis7种数据类型_Redis_72

  • 通过 xgroup create mystream groupA $ 指令可以创建一个 mystream 消费组,从流的尾部开始消费
  • 如果将 $ 替换为 0 代表从流的首部开始消费 【创建消费组的时候必须指定 ID】
  • 通过 xreadgroup group 消费组 消费者 streams 消息流 指令可以读取流中的信息
  • 不同消费组的消费者可以消费同一条消息
  • 消费组的目的是什么呢?
  • 让组内的多个消费者共同分担读取消息,所以,我们通常会让每个消费者读取部分消息,从而实现消息读取负载在多个消费者间是均衡分布的
  • 通过 xpending mystrean groupA 指令可以查看我们 mystream 消费组的 groupA 消费者已读取但还未确认的信息
  • 通过 xack mystream group-name 序列号 指令可以向消息队列确认消息处理已完成

新版本redis的数据类型 redis7种数据类型_Redis_73

  • 通过 xinfo stream mystream 指令可以打印消费组的详细信息

(3)特殊符号说明

  • - + 表示最小和最大可能出现的 id
  • $ 表示只消费最新的信息,当前流中最大的 id,可用于将要来到的消息
  • > 用于 xreadgroup 命令,表示迄今还没有发送给组中使用者的消息,会更新消费者组的最后 ID
  • * 用于 XADD命令中,让系统自动生成 id

3.10 bitfield 位域

  • 主要的作用:位域修改、溢出控制
  • 将一个 Redis 字符串看作是一个由二进制位组成的数组,并能对变长位宽和任意没有字节对齐的指定整型位域进行寻址和修改

新版本redis的数据类型 redis7种数据类型_学习_74


🌔 基本命令


  • BITFIELD key [GET type offset]
  • 新版本redis的数据类型 redis7种数据类型_数据库_75


  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_76


  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_77

  • hello 等价于 0110100001100101011011000110110001101111
  • 新版本redis的数据类型 redis7种数据类型_Redis_78


  • BITFIELD key [SET type offset value]
  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_79


  • 新版本redis的数据类型 redis7种数据类型_新版本redis的数据类型_80


  • BITFIELD key [INCRBY type offset increment]
  • 新版本redis的数据类型 redis7种数据类型_redis_81

  • 溢出控制 OVERFLOW[WRAP|AST|FAIL]

  • WRAP:使用回绕(wrap around)方法处理有符号整数和无符号整数的溢出情况
  • 新版本redis的数据类型 redis7种数据类型_redis_82


  • SAT:使用饱和计算(saturation arithmetic)方法处理益出下溢计算的结果为最小的整数值,而上溢计算的结果为最大的整数值
  • 新版本redis的数据类型 redis7种数据类型_学习_83

  • FAIL:命令将拒绝执行那些会导致上溢或者下溢情况出现的计算并向用户返回空值表示计算未被执行

新版本redis的数据类型 redis7种数据类型_redis_84