HyperLogLog 是用来做基数统计的算法,优点在于输入元素的数量或体积很大时,计算基数所需的空间总是固定且很小 【基数统计】
在 Redis 中 每个 HyperLogLog 键只需要花费 12KB内存,就可以计算接近 2^64 个不同元素的基数,这和计算基数时元素越多耗费内存越多的集合形成鲜明对比
但是,因为 HyperLogLog 只会根据输入元素计算基数,而不会存储输入元素本身,所以 HyperLogLog 不能像集合那样返回输入的各个元素
通过 bitfield 命令可以一次性操作多个比特域(连续的多个比特位),它会执行一系列操作并返回一个响应数组,这个数组中的元素对应参数列表中的相应操作的执行结果 【位域】
总结,通过 bitfield 命令可以为我们一次性对多个比特域进行操作
Redis 的 Stream 类型是 Redis5.0 版本新增加的数据结构
Redis 的 Stream 主要用于消息队列(Message Queue),Redis 本身有一个 发布订阅(pub/sub)来实现消息队列的功能
Redis 的 Stream 提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每个客户端的访问位置,保证消息不丢失
我们可以通过 英文/中文 官网去查询Redis常见数据类型的操作命令:
1、设置、获取、遍历全部 key
set k1 v1
可以创建一个名为 k1 的 key,它的 value 为 v1get k1
可以获取名为 k1 的 key 对应的 valuekeys *
可以打印出当前数据库中的所有 key2、判断某个 key 是否存在,判断属于什么类型
exists key
可以判断我们指定的 key 是否存在type key
可以查看我们指定的 key 属于哪种类型3、删除我们的key
del key
可以直接删除我们的 key 数据 【如果当前要删除的是超大文件,就可能导致出现线程阻塞的现象】unlink key
可以实现非阻塞删除,仅仅将 keys 从 keyspace 元数据中删除,真正的删除会在后续异步中操作4、为我们的key设置过期时间,查看key还有多久过期
ttl key
可以查看我们的key还有多少秒过期 【-1代表永不过期,-2代表已经过期】expire key 秒钟
可以为我们的key设置过期时间5、切换数据库、查看当前数据库中key的数量、移动key所属数据库
6、清空
help @数据类型
指令查看相关帮助文档set key value
指令可以创建一个 key
set key value [NX|XX] [GET] [EX seconds|PX milliseconds|EXAT unix-time-seconds|PXAT unix-time-milliseconds|KEEPTTL]
System.out.println(Long.toString(System.currentTimeMillis() / 1000L));
get key
指令可以获取 key 对应的 valuenx、xx 参数测试
ex 参数测试 【其他几个过期时间用法同理】
2、同时设置/获取多个键值
3、获取指定区间范围内的值
通过 getrange key idx1 idx2
指令可以获取 key 键对应索引为 idx1 到 idx2 范围 的 value 部分值
通过 setrange key idx value
指令可以将 key 从 idx 索引开始用 value 覆盖对应位置的元素
4、数值运算 【前提条件 value 是数字】
incr key
指令可以将 key 对应的 value 加一decr key
指令可以将 key 对应的 value 减一incrby key increment
指令可以将 key 对应的 value 加 incrementdecrby key decrement
指令可以将 key 对应的 value 减 decrement5、获取字符串长度和内容追加
strlen key
可以获取 key 对应的 value 的长度append key value
可以在 key 对应的 value 的末尾追加上指定的 value 的内容6、分布式锁
7、getset 指令
8、应用场景
lpush list value [value ...]
指令可以创建一个 list 类型的key,value是对应的值,从左侧进入队列【可以创建一个或多个value】roush list value[value ...]
指令可以创建一个 list 类型的key,value是对应的值,从右侧进入队列lrange list start end
指令可以从左到右遍历 start-end 索引内的所有元素并输出 【0 -1 代表所有】2、删除列表中的元素
lpop list
指令可以从首部删除 list 的一个元素rpop list
指令可以从尾部删除 list 的一个元素3、获取元素和获取元素的个数
lindex list index
指令可以获取 list 列表,index 索引处的元素值 【index的排序可以理解为从上到下、从左到右】通过 llen list
指令可以获取 list 列表中元素的个数4、批量删除和截取
lrem key count value
指令可以删除 count 个值为 value 的元素,返回值为实际删除的数量 【如果count为零,就代表删除所有值】5、移动、修改、插入元素
通过 通过rpoplpush list1 list2
指令可以从 list1 列表的尾部弹出一个元素,然后从 list2 列表的首部进入
通过 linsert list before/after value value2
指令可以在 list 的 value 前或后插入元素元素 value2 【value是 list 中已经存在的元素】
6、应用场景
通过 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 对应的值
通过 hdel hash1 field1 field2
指令可以删除 hash 中 field1 和 field2 对应的键值对
2、算数运算
通过 hincrby hash1 field1 number1
指令可以让 hash1 的 field1 对应的值加上 number1 【整型数】
通过 hincrbyfloat hash2 field2 number2
指令可以让 hash2 的 field2 对应的值加上 number2 【浮点数】
通过 hsetnx hash1 field1 value1
指令可以在创建 hash1 的时候判断是否为不存在的键,存在了就不创建了
通过 hkeys hash1
指令可以获取 hash1 中所有的 field
1、常用方法
通过 sadd key member [member ...]
指令可以创建一个 key 集合,同时可以创建一个或多个值
通过 srem key member [member ...]
指令可以删除 key 集合中的 member 元素
通过 smove key1 key2 member
指令可以将 key1 集合中的 member 元素移除并添加到 key2 集合中
2、集合运算
集合的交集运算,我们可以通过 sinter key [key ...]
指令完成
(1)微信抽奖小程序
需求 | 实现 |
---|---|
1 用户ID,立即参与按钮 | sadd key 用户ID |
2 显示已经有多少人参与了,上图23208人参加 | SCARD key |
3 抽奖(从set中任意选取N个中奖人) | SRANDMEMBER key 2 随机抽奖2个人,元素不删除SPOP key 3 |
(2) 朋友圈点赞查看共同点赞的好友
需求 | 实现 |
---|---|
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推荐可能认识的人
通过 zadd key score member [score member ...]
指令可以向 zset 集合中添加元素
通过 zrange key start stop [withscores]
指令可以遍历输出指定范围的元素,也可以携带上分数【升序】
通过 zrevrange key start stop [withscores]
指令和上面的遍历类似,只不是是逆序输出
通过 zrangebyscore key min max [withscores] [limit offset count]
指令可以获取指定分数范围内的元素
通过 zscore key member
指令可以获取 key 集合中 member 元素对应的 score
通过 zincrby key increment member
指令可以为key集合中的member 元素加上 increment
通过 zmpop numkeys key [key...] [min | max count]
可以删除numkeys个 key
通过 zrank key values
可以获取 key 集合中 value 对应的下标值 【默认是score从小到大排序】
应用场景:根据商品销售量对商品进行排序显示
需求 | 实现 |
---|---|
商品编号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 |
通过 setbit key offset value
指令可以将 key 位图的 offset 索引位置的值设置为 value【索引(偏移量)是从零开始的】
通过 strlen key
可以统计key位图所占字节数(8bit为一个字节)【具体使用了多少位看我们设置offset最大使用到了哪里】
通过bitop 操作 key3 key1 key2
指令可以将位图 key1 和 key2 按位进行指定的操作,并将操作的结果保存到位图 key3 中
应用场景
可以统计一个用户一年的登录记录
此外,在实际使用时,最好对Bitmap设置过期时间,让Redis自动删除不再需要的签到记录以节省内存开销
基本命令
应用案例
可以应用在 网站首页亿级 UV 的 Redis 统计方案
可以用于统计某个用户每天搜索不同词条个数
核心思想就是将球体转换为平面,区块转换为一点,将一维的点块转换为二进制再通过 base 编码
底层是由 ZSet 实现的,所以我们就可以使用一些 ZSet 的方法
基本命令
我们可以通过下面这个网站 查询某个地址的经纬度
通过 geoadd key longitude latitude member[longitude latitude member..]
指令可以在地理空间 key 中创建一个或多个 member 位置的 longitude 经度、latitude 维度
通过 geohash key member [member...]
指令可以获取地理空间 key 的一个或多个位置特殊编码后的值 【就是将经度和纬度整合成一个特殊的数据】
通过 geodist key member1 member2 [m|km|ft|mi]
指令可以计算一个地理空间中两个位置的距离
通过 georadius key 指定位置经纬度 距离 单位 withdist withcoord count n withhash desc
指令可以在指定位置为中心,查找指定半径范围内所有位置,并显示出他们的经纬度、与中心位置的距离,以距离升序的方式显示出 n 条记录
通过 georadiusbymember key member-name distance unit withdist withcoord count n withhash
也是按半径查找位置,只不过中心点是我们地理空间中已经存在的一个位置
应用场景
美团地图位置附近酒店推送
高德地图附近的核酸检查点
先介绍一些流相关的概念
该数据类型是在 Redis5.0 版本新增的,属于Redis版的 消息中间件 + 阻塞队列
之前Redis 实现消息队列有两种方式:
我们的 Stream 可以实现消息队列,支持消息的持久化、支持自动生成全局唯一ID、支持ACK确认消息的模式,支持消费组模式等,让消息队列更加的稳定和可靠
Stream 底层结构和原理说明:
我们可以看出,一个消息链表,将所有加入的消息都串起来,每个消息都有唯一的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:确认字符),它用来确保客户端至少消费了消息一次,而不会在网络传输的中途丢失了没处理 |
基本操作
通过 xadd key * field value [field value ...]
指令可以向 key 流中添加一个或多个 field-value 【不论多少个键值对,添加一次为一个完整的消息】
通过 range key start end count n
指令可以按从小到大遍历出 key 流中的前n条记录
通过 xrevrange key start end count n
指令和上面的功能类似,只是逆序进行输出
通过 xread [count] [block milliseconds] streams key [key...] ID [ID ...]
指令可以读取消息
非阻塞:
阻塞:就是流中没有信息,需要等待信息到达再读取
(2)消费组相关指令
xgroup create mystream groupA $
指令可以创建一个 mystream 消费组,从流的尾部开始消费
xreadgroup group 消费组 消费者 streams 消息流
指令可以读取流中的信息xpending mystrean groupA
指令可以查看我们 mystream 消费组的 groupA 消费者已读取但还未确认的信息xack mystream group-name 序列号
指令可以向消息队列确认消息处理已完成(3)特殊符号说明
- +
表示最小和最大可能出现的 id$
表示只消费最新的信息,当前流中最大的 id,可用于将要来到的消息>
用于 xreadgroup 命令,表示迄今还没有发送给组中使用者的消息,会更新消费者组的最后 ID*
用于 XADD命令中,让系统自动生成 id