当前位置: 首页 > news >正文

【Redis】基于Redis6的数据类型以及相关命令、应用场景整理

文章目录

  • 数据类型与命令
    • 常用
      • 字符串(String)
      • 列表(List)
      • 集合(Set)
      • 有序集合(Sorted Set)
      • 哈希(Hash)
    • 特殊
      • 地理位置(GEO)
      • 流(Stream)
      • 基数统计(HyperLogLog)
      • 位图(Bitmap)

数据类型与命令

Redis在线测试:http://try.redis.io/,可用来练习大部分命令

Redis命令官方文档:https://redis.io/commands/

常用

字符串(String)

Redis的String能表达3种值的类型:字符串、整数、浮点数。

应用场景:

  • 分布式全局自增id

    使用incr递增数字

  • 普通的字符串缓存

  • setnx用于分布式锁

    当value不存在时采用赋值,可用于实现分布式锁

常用命令:

命令用法示例描述
SETSET key value赋值,设置key对应的value
如果对一个key执行多次SET操作,则会覆盖之前的值
GETGET key取值,获取key对应的value
MGETMGET key1 [key2…]获取所有(一个或多个)给定key的值
MSETMSET key value [key value …]同时设置一个或多个key-value对
GETSETGETSET key value赋值并获取旧的值,Redis 6.2.0版本之后,这个命令已经被标记为过时的,可用SET命令 + GET作为参数替代
SETNXSETNX key value当value不存在时才赋值
SETEXSETEX key seconds value设置key对应的value,并将key的过期时间设为seconds(以秒为单位)
STRLENSTRLEN key返回key所储存的字符串值的长度
INCRINCR key将key中储存的数字值加一
INCRBYINCRBY key increment将key所储存的值加上给定的增量值(increment)
DECRDECR key将key中储存的数字值减一
DECRBYDECRBY key decrement将key所储存的值减去给定的减量值(decrement)
APPENDAPPEND key value如果key已经存在并且是一个字符串, APPEND命令将指定的value追加到该key原来值的末尾
如果key不存在,则类似SET命令,初始化一个key-value键值对

示例:

127.0.0.1:6379> set test-key hello #设置test-key的value为hello
OK
127.0.0.1:6379> get test-key #获取test-key的值
"hello"
127.0.0.1:6379> 
127.0.0.1:6379> del test-key #删除key
(integer) 1
127.0.0.1:6379> 
127.0.0.1:6379> get test-key #删除后,获取不存在的key返回nil
(nil)
127.0.0.1:6379> 
127.0.0.1:6379> getset color red #赋值并获取,key没有旧值返回nil
(nil)
127.0.0.1:6379> getset color green #赋值并获取之前的值
"red"
127.0.0.1:6379> 
127.0.0.1:6379> set message hello
OK
127.0.0.1:6379> append message world #拼接指定字符串至key对应的value后
(integer) 10
127.0.0.1:6379> get message
"helloworld"
127.0.0.1:6379> 
127.0.0.1:6379> set count 0
OK
127.0.0.1:6379> incr count #将count对应的数值加1
(integer) 1
127.0.0.1:6379> incrby count 10 #将count对应的数值加10
(integer) 11
127.0.0.1:6379> decr count #将count对应值减1
(integer) 10
127.0.0.1:6379> 

列表(List)

List列表类型可以存储有序、可重复的元素。Redis列表是简单的字符串列表,按照插入顺序排序,你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

应用场景:

  • 作为栈或队列使用

​ 列表有序,结合不同的命令可以模拟栈(先入后出)或队列(先入先出);

  • 可用于各种列表,比如用户列表、商品列表、评论列表等

常用命令:

命令用法示例描述
LPOPLPOP key [count]移除并获取列表头部的一个或几个元素(从左边移除并获取)
RPOPRPOP key [count]移除并获取列表尾部的一个或几个元素(从右边移除并获取)
LPUSHLPUSH key value1 [value2…]向列表左边(头部)添加一个或多个值
RPUSHRPUSH key value1 [value2…]向列表右边(尾部)添加一个或多个值
LLENLLEN key获取列表长度
LRANGELRANGE key start stop获取列表指定范围内的元素
LREMLREM key count element删除列表元素
count > 0 : 从左至右删除和element相等的指定个数的元素
count < 0 : 从右至左删除和element相等的指定个数的元素
count = 0 : 删除所有和element相等的元素
LSETLSET key index value通过索引设置列表元素的值
LINDEXLINDEX key index通过索引获取列表中的元素

示例:

127.0.0.1:6379> rpush language java c c++ go python php ruby # 向列表中依次从左至右添加7个元素
(integer) 7
127.0.0.1:6379> lpush language scala #从列表左边添加一个元素
(integer) 8
127.0.0.1:6379> lrange language 0 7 #查看所有列表数据,注意:下表是从0开始的
1) "scala"
2) "java"
3) "c"
4) "c++"
5) "go"
6) "python"
7) "php"
8) "ruby"
127.0.0.1:6379> rpop language #从右边移除并获取(弹出)一个元素
"ruby"
127.0.0.1:6379> llen language
(integer) 7
127.0.0.1:6379> lpop language 2 #从左边移除并获取(弹出)两个元素
1) "scala"
2) "java"
127.0.0.1:6379> llen language
(integer) 5
127.0.0.1:6379> lrange language 0 4
1) "c"
2) "c++"
3) "go"
4) "python"
5) "php"
127.0.0.1:6379> lindex language 2 #获取列表中坐标为2(第三个)元素
"go"
127.0.0.1:6379> 
127.0.0.1:6379> lset language 2 c# #将坐标为2的元素go替换为c#
OK
127.0.0.1:6379> lindex language 2
"c#"
127.0.0.1:6379> 

问题:

如何使用Redis的List结构实现队列和栈?

  • 队列:(保证添加和移除方向相反即可)

    RPUSH + LPOP (所有数据从尾部/右边添加、从头部/左边移除)<更贴近生活>

    LPUSH + RPOP

  • 栈:(保证添加和移除方向相同即可)

    LPUSH + LPOP (所有数据从头部添加、从头部移除)<更贴近栈的实现>

    RPUSH + RPOP

集合(Set)

Redis的Set是String类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

应用场景:

  • 黑白名单

    使用SISMEMBER命令可快速判断元素是否在集合内

  • 共同好友、可能认识的人

    使用SINTER、SDIFF命令可判断两个集合的交集、差集

常用命令:

命令用法示例描述
SADDSADD key member1 [member2…]向集合添加一个或多个成员
SCARDSCARD key获取集合的成员数
SMEMBERSSMEMBERS key返回集合中的所有成员
SPOPSPOP key返回集合中的一个随机元素,并删除该元素
SRANDMEMBERSRANDMEMBER key [count]返回集合中一个或多个随机元素,不会删除该元素
SREMSREM key member1 [member2]移除集合中一个或多个元素,不会返回该元素
SISMEMBERSISMEMBER key member判断元素是否在集合内
SINTERSINTER key1 [key2…]返回给定所有集合的交集(相同的元素)
SDIFFSDIFF key1 [key2…]返回给定所有集合在第一个指定的集合中的公共差集(不相同的元素)
SUNIONSUNION key1 [key2…]返回给定所有集合的并集(合并所有集合)

示例:

127.0.0.1:6379> sadd languages:lucy java python golang # Lucy掌握的变成语言
(integer) 3
127.0.0.1:6379> sadd languages:tony java scala c # Tony掌握的变成语言
(integer) 3
127.0.0.1:6379> sadd languages:henry java python php # Henry掌握编程语言
(integer) 3
127.0.0.1:6379> scard languages:lucy # 查看集合成员数
(integer) 3
127.0.0.1:6379> smembers languages:lucy # 查看集合所有成员
1) "java"
2) "golang"
3) "python"
127.0.0.1:6379> sdiff languages:lucy languages:henry # 查看Lucy掌握的语言中,Henry不掌握的
1) "golang"
127.0.0.1:6379> sdiff languages:henry languages:lucy # 查看Henry掌握的语言中,Lucy不掌握的
1) "php"
127.0.0.1:6379> sdiff languages:lucy languages:henry languages:tony # 查看Lucy掌握的语言中,Henry和Tony都不掌握的
1) "golang"
127.0.0.1:6379> sinter languages:lucy languages:henry # 查看Lucy和Henry掌握的共同语言
1) "java"
2) "python"
127.0.0.1:6379> sunion languages:lucy languages:henry # 查看Lucy和Henry两人掌握的所有语言
1) "java"
2) "golang"
3) "php"
4) "python"
127.0.0.1:6379> 
127.0.0.1:6379> sismember languages:lucy java # 判断Lucy是否掌握Java (1代表true,0代表false)
(integer) 1
127.0.0.1:6379> sismember languages:lucy c
(integer) 0
127.0.0.1:6379> 
127.0.0.1:6379> spop languages:tony # 随机取出并删除一个集合元素
"scala"
127.0.0.1:6379> smembers languages:tony 
1) "java"
2) "c"
127.0.0.1:6379> 

有序集合(Sorted Set)

Redis 有序集合又叫Zset,和Set一样也是String类型元素的集合,且不允许重复的成员,不同的是每个元素都会关联一个Double类型的分数。Redis正是通过分数来为集合中的成员进行排序。

有序集合的成员是唯一的,但分数(Score)却可以重复。

应用场景:

由于可以按照分值排序,所以适用于各种排行榜。比如:点击排行榜、销量排行榜、搜索排行榜等。

常用命令:

命令用法示例描述
ZADDZADD key score1 member1 [score2 member2]向有序集合添加一个或多个成员,或者更新已存在成员的分数
ZCARDZCARD key获取有序集合的成员数
ZCOUNTZCOUNT key min max返回有序集合中score值在[min,max]区间的元素数量
ZINCRBYZINCRBY key increment member集合中对指定成员的分数加上增量 increment
ZSCOREZSCORE key member返回有序集合中,成员的分数值
ZRANKZRANK key member获得有序集合中member的排名(按分值从小到大),需要注意的是,排名序号是从0开始的
ZREVRANKZREVRANK key member获得有序集合中member的排名(按分值从大到小)
ZRANGEZRANGE key start stop [WITHSCORES]获得有序集合中指定排名区间成员,按分数递增排序
ZREVRANGEZREVRANGE key start stop [WITHSCORES]获得有序集合中指定排名区间成员,按分数递减排序
ZREMZREM key member [member …]移除有序集合中的一个或多个成员

示例:

127.0.0.1:6379> zadd examination 80.5 xiaozhao 87.0 xiaoli 76.5 xiaowang 92 xiaozhang # 添加四名学生的考试成绩到有序集合
(integer) 4
127.0.0.1:6379> zcard examination # 查看成员数
(integer) 4
127.0.0.1:6379> 
127.0.0.1:6379> zcount examination 80 90 # 统计成绩在80~90分的数量
(integer) 2
127.0.0.1:6379> zscore examination xiaoli # 查看小李的成绩
"87"
127.0.0.1:6379> zrank examination xiaoli # 查看小李的分数排名(从小到大)<注:起始为0>
(integer) 2
127.0.0.1:6379> zrevrank examination xiaoli # 查看小李的分数排名(从大到小)
(integer) 1
127.0.0.1:6379> zrange examination 0 2 withscores # 查看成绩倒数三名
1) "xiaowang"
2) "76.5"
3) "xiaozhao"
4) "80.5"
5) "xiaoli"
6) "87"
127.0.0.1:6379> 
127.0.0.1:6379> zrevrange examination 0 2 withscores # 查看成绩正数三名
1) "xiaozhang"
2) "92"
3) "xiaoli"
4) "87"
5) "xiaozhao"
6) "80.5"

哈希(Hash)

Redis Hash是一个String类型的Field(字段)和Value(值)的映射表,也称作散列表、哈希表、字典,Hash特别适合用于存储对象。

应用场景:

  • 更适合存储结构化的数据,如对象的存储 ,表数据的映射。

  • 购物车
    以用户id作为key,每位用户创建一个hash存储结构存储对应的购物车信息
    将商品编号作为field,购买数量作为value进行存储

常用命令:

命令用法示例描述
HSETHSET key field value单个字段赋值,将哈希表key中的字段field的值设为value,如果该field之前有值,则做更新操作
HMSETHMSET key field1 value1 [field2 value2…]给多个字段赋值
HSETNXHSETNX key field value只有在字段field不存在时,设置哈希表字段的值
HGETHGET key field获取存储在哈希表中指定字段的值
HMGETHMGET key field1 [field2…]获取所有给定字段的值
HGETALLHGETALL key获取在哈希表中指定key的所有字段和值
HEXISTSHEXISTS key field查看哈希表key中,指定的字段是否存在
HDELHDEL key field1 [field2…]删除一个或多个哈希表字段
HKEYSHKEYS key获取所有哈希表中的字段
HLENHLEN key获取所有哈希表长度(field-value映射数量)
HVALSHVALS key获取所有哈希表中的值

示例:

127.0.0.1:6379> hmset user:zhangfei username zhangfei password 123456 age 23 sex male # 批量给user:zhangfei赋值
OK
127.0.0.1:6379> hkeys user:zhangfei # 获取所有的字段名
1) "username"
2) "password"
3) "age"
4) "sex"
127.0.0.1:6379> hvals user:zhangfei # 获取所有的值
1) "zhangfei"
2) "123456"
3) "23"
4) "male"
127.0.0.1:6379> hexists user:zhangfei address # 检查字段是否存在
(integer) 0
127.0.0.1:6379> hexists user:zhangfei age
(integer) 1
127.0.0.1:6379> hdel user:zhangfei password # 删除指定字段
(integer) 1
127.0.0.1:6379> hkeys user:zhangfei 
1) "username"
2) "age"
3) "sex"
127.0.0.1:6379> hlen user:zhangfei # 查看field-value映射数量
(integer) 3
127.0.0.1:6379> 
127.0.0.1:6379> hgetall user:zhangfei # 获取所有field以及对应的value
1) "username"
2) "zhangfei"
3) "age"
4) "23"
5) "sex"
6) "male"
127.0.0.1:6379> 

特殊

地理位置(GEO)

Redis GEO主要用于存储地理位置信息,并对存储的信息进行操作,该功能在Redis 3.2版本新增。

应用场景:

1、记录地理位置

2、计算外卖配送-骑手距离

3、查找"附近的人"

4、搜索某地附近的美食

常用命令:

命令用法示例描述
GEOADDGEOADD key longitude latitude member [longitude latitude member …]用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中
GEOPOSGEOPOS key member [member …]从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil。
GEODISTGEODIST key member1 member2 [m|km|ft|mi]返回两个给定位置之间的距离
m :米,默认单位
km :千米
mi :英里
ft :英尺
GEORADIUSGEORADIUS key longitude latitude radius [m|km|ft|mi]以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素
GEORADIUSBYMEMBERGEORADIUSBYMEMBER key member radius以给定的成员为中心,返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素

示例:

127.0.0.1:6379> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania" # 给西西里岛添加两座地点:巴勒莫和卡塔尼亚,并分别指定经纬度
(integer) 2
127.0.0.1:6379> GEODIST Sicily Palermo Catania km # 计算两个地点的距离
"166.2742"
127.0.0.1:6379> GEORADIUS Sicily 15 37 200 km # 列举以(15,37)为中心,相距200km的地点
1) "Palermo"
2) "Catania"
127.0.0.1:6379> GEORADIUS Sicily 15 37 200 km WITHDIST # 列举以(15,37)为中心,相距200km的地点,并计算其距离
1) 1) "Palermo"
   2) "190.4424"
2) 1) "Catania"
   2) "56.4413"
127.0.0.1:6379> GEOPOS Sicily Palermo # 查询指定地点的经纬度
1) 1) "13.36138933897018433"
   2) "38.11555639549629859"
127.0.0.1:6379> 
127.0.0.1:6379> GEORADIUSBYMEMBER Sicily Palermo 200 km # 列举以指定地点为中心,相距200km的地点(结果包含本身)
1) "Palermo"
2) "Catania"
127.0.0.1:6379> 
127.0.0.1:6379> GEORADIUSBYMEMBER Sicily Palermo 1 km
1) "Palermo"
127.0.0.1:6379> 
127.0.0.1:6379> 

流(Stream)

Redis Stream 是 Redis 5.0 版本新增加的数据结构。

Redis Stream 主要用于消息队列(MQ,Message Queue),Redis 本身是有一个 Redis 发布订阅 (pub/sub) 来实现消息队列的功能,但它有个缺点就是消息无法持久化,如果出现网络断开、Redis 宕机等,消息就会被丢弃。

简单来说发布订阅 (pub/sub) 可以分发消息,但无法记录历史消息。而 Redis Stream提供了消息的持久化和主备复制功能,可以让任何客户端访问任何时刻的数据,并且能记住每一个客户端的访问位置,还能保证消息不丢失。

每个Stream都有唯一的名称,它就是 Redis 的 key,在我们首次使用 xadd 指令追加消息时自动创建。

应用场景:

订单处理

消息队列

聊天室

常用命令:

命令用法示例描述
XADDXADD key ID field value [field value …]向队列添加消息,消息由一组或多组field-value组成,如果指定的队列不存在,则先创建一个队列
ID:消息 id,我们使用 * 表示由 redis 生成,可以自定义,但是要自己保证递增性
XREADXREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key …] id [id …]从一个或多个Stream中读取消息,可指定读取的数量,是否以阻塞的方式去取,以及从每个Stream读取消息的起始id (不包含指定id)
XLENXLEN key获取队列包含的元素数量,即队列长度
XDELXDEL key ID [ID …]根据id删除队列中的一条或者多条消息
XRANGEXRANGE key start end [COUNT count]消息id从小到大,读取队列中给定ID范围的消息
key :队列名
start :开始值, - 表示最小值
end :结束值, + 表示最大值
count :数量
XREVRANGEXREVRANGE key end start [COUNT count]消息id从大到小,读取队列中给定ID范围的消息
XGROUP CREATEXGROUP CREATE key groupname id-or-$创建消费组
key:指定消费的队列名称,如果不存在就创建
groupname:组名
id-or- :指定从哪消费,可指定从具体的 i d 开始消费,如果设置为 : 0 − 0 ,表示从头开始消费,也可设置为 : 指定从哪消费,可指定从具体的id开始消费,如果设置为: 0-0,表示从头开始消费,也可设置为 :指定从哪消费,可指定从具体的id开始消费,如果设置为:00,表示从头开始消费,也可设置为,表示从尾部开始消费,只接受新消息,当前 Stream旧的消息会全部忽略
XGROUP SETIDXGROUP SETID key groupname id-or-$修改一个消费组从那开始消费
XGROUP DESTROYXGROUP DESTROY key groupname删除指定消费组
XREADGROUP GROUPXREADGROUP GROUP group consumer [COUNT count] [BLOCK milliseconds] [NOACK] STREAMS key [key …] id [id …]和XREAD相似,指定消费者组进行读取消息
group:消费组名,需要提前创建
consumer:消费者名,一个消费组可以由多名消费者组成,同时消费一个Stream,会自动创建(也可以使用命令创建),如果消息队列中的消息被消费组的一个消费者消费了,这条消息就不会再被这个消费组的其他消费者读取到
id:这里的id含义比较特殊,在后面解释
XGROUPXGROUP CREATECONSUMER key groupname consumername创建一个消费组的消费者
XACKXACK key group id [id …]将消息标记为”已处理“
ACK:acknowledge的缩写,消息队列的一种确认机制,客户端收到消息或处理完业务之后,告知服务端消息已正常消费

示例:

127.0.0.1:6379> xadd order * name iphone type "iphone 13 pro max" storage 256GB color blue  # 创建队列order,并添加一条消息流
"1661169438466-0"
127.0.0.1:6379> xadd order * name iphone type "iphone 13 pro" storage 128GB color white  # 向Stream中添加消息流
"1661169496826-0"
127.0.0.1:6379> xlen order # 查看消息数量
(integer) 2
127.0.0.1:6379> xdel order 1661169496826-0 # 根据id删除消息
(integer) 1
127.0.0.1:6379> xlen order 
(integer) 1
127.0.0.1:6379> xrange order - + # 获取指定范围内的所有消息
1) 1) "1661169438466-0"
   2) 1) "name"
      2) "iphone"
      3) "type"
      4) "iphone 13 pro max"
      5) "storage"
      6) "256GB"
      7) "color"
      8) "blue"
127.0.0.1:6379> xread streams order 0-0 # 从起始位置读取所有消息
1) 1) "order"
   2) 1) 1) "1661169438466-0"
         2) 1) "name"
            2) "iphone"
            3) "type"
            4) "iphone 13 pro max"
            5) "storage"
            6) "256GB"
            7) "color"
            8) "blue"
127.0.0.1:6379> 
127.0.0.1:6379> xadd order * name Xiaomi type "Xiaomi 12 ultra" storage 512GB color black 
"1661224305535-0"
127.0.0.1:6379> xread streams order 1661169438466-0 # 从大于id:1661169438466-0的地方开始读取所有消息
1) 1) "order"
   2) 1) 1) "1661224305535-0"
         2) 1) "name"
            2) "Xiaomi"
            3) "type"
            4) "Xiaomi 12 ultra"
            5) "storage"
            6) "512GB"
            7) "color"
            8) "black"
127.0.0.1:6379> 
127.0.0.1:6379> xgroup create order warehouse 0-0 # 创建order的消费者组warehouse,指定从队列最开始位置消费
OK
127.0.0.1:6379> xinfo stream order # 查看order队列的信息
 1) "length"
 2) (integer) 2
 3) "radix-tree-keys"
 4) (integer) 1
 5) "radix-tree-nodes"
 6) (integer) 2
 7) "last-generated-id"
 8) "1661224305535-0"
 9) "groups"
10) (integer) 1
11) "first-entry"
12) 1) "1661169438466-0"
    2) 1) "name"
       2) "iphone"
       3) "type"
       4) "iphone 13 pro max"
       5) "storage"
       6) "256GB"
       7) "color"
       8) "blue"
13) "last-entry"
14) 1) "1661224305535-0"
    2) 1) "name"
       2) "Xiaomi"
       3) "type"
       4) "Xiaomi 12 ultra"
       5) "storage"
       6) "512GB"
       7) "color"
       8) "black"
127.0.0.1:6379> xinfo groups order # 查看order队列的所有消费组信息
1) 1) "name"
   2) "warehouse"
   3) "consumers"
   4) (integer) 0
   5) "pending"
   6) (integer) 0
   7) "last-delivered-id"
   8) "0-0"
127.0.0.1:6379> 
127.0.0.1:6379> xgroup create order store 0-0
OK
127.0.0.1:6379> xgroup createconsumer order store consumer-1 # 手动创建消费者
(integer) 1
127.0.0.1:6379> xreadgroup group store consumer-1 count 2 streams order >  # 消费新消息
1) 1) "order"
   2) 1) 1) "1661169438466-0"
         2) 1) "name"
            2) "iphone"
            3) "type"
            4) "iphone 13 pro max"
            5) "storage"
            6) "256GB"
            7) "color"
            8) "blue"
      2) 1) "1661224305535-0"
         2) 1) "name"
            2) "Xiaomi"
            3) "type"
            4) "Xiaomi 12 ultra"
            5) "storage"
            6) "512GB"
            7) "color"
            8) "black"
127.0.0.1:6379> 
127.0.0.1:6379> xreadgroup group store consumer-1 count 2 streams order 0-0 # 读取pending状态的消息
1) 1) "order"
   2) 1) 1) "1661169438466-0"
         2) 1) "name"
            2) "iphone"
            3) "type"
            4) "iphone 13 pro max"
            5) "storage"
            6) "256GB"
            7) "color"
            8) "blue"
      2) 1) "1661224305535-0"
         2) 1) "name"
            2) "Xiaomi"
            3) "type"
            4) "Xiaomi 12 ultra"
            5) "storage"
            6) "512GB"
            7) "color"
            8) "black"
127.0.0.1:6379> 

注意:

使用XREADGROUP时,要在STREAMS选项后面指定id,可以是以下两种类型之一:

  • 特殊标识:>,这意味着消费者只希望接收从未传递给任何其他消费者的消息,这意味着消费新的消息。

  • 任何其他id,即0或任何其他有效id或不完整id,达到的效果是:在处于pending状态的消息列表中,返回大于指定id的消息。因此,基本上,如果id不是 ‘>’ ,那么该命令将只允许客户端访问其pending的条目:即传递给它但尚未确认的消息。注意,在这种情况下,BLOCK和NOACK都被忽略。

这里比较不易理解,消费最新的消息,使用第一种方式即可,第二种方式,更像是为了处理消息被消费者消费了,但是程序异常或不可抗力的因素导致消息未ack的情况,是一种补偿措施。或者简单地用来查看处于pending状态的消息。

基数统计(HyperLogLog)

Redis 在 2.8.9 版本添加了 HyperLogLog 结构。

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

什么是基数?

比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8},基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。

应用场景:

估算一个游戏的日活量

估算一个游戏公司旗下多款游戏的日活总量

估算一个网站被多少用户访问过

常用命令:

命令用法示例描述
PFADDPFADD key element [element…]添加指定元素到 HyperLogLog中
PFCOUNTPFCOUNT key [key …]返回给定 HyperLogLog 的基数估算值
PFMERGEPFMERGE destkey sourcekey [sourcekey …]将多个 HyperLogLog 合并为一个 HyperLogLog

示例:

127.0.0.1:6379> pfadd numbers 1 3 2 5 3 4 6 9 10 # 添加元素
(integer) 1
127.0.0.1:6379> pfcount numbers # 查看基数预估值
(integer) 8
127.0.0.1:6379> 

位图(Bitmap)

在平时开发过程中,经常会有一些 bool 类型数据需要存取。比如记录用户一年内签到的次数,签了是 1,没签是 0。如果使用 key-value 来存储,那么每个用户都要记录 365 次,当用户成百上亿时,需要的存储空间将非常巨大。为了解决这个问题,Redis 提供了位图结构。

位图(Bitmap)同样属于 string 数据类型。Redis 中一个字符串类型的值最多能存储 512 MB 的内容,每个字符串由多个字节组成,每个字节又由 8 个 Bit 位组成。位图结构正是使用“位”来实现存储的,它通过将比特位设置为 0 或 1来达到数据存取的目的,这大大增加了 value 存储数量。

应用场景:

用户签到

统计一个月内每天都登陆过游戏的用户

统计超过一个月未登录游戏的用户

统计用户活跃数量

常用命令:

命令用法示例描述
SETBITSETBIT key offset value用来设置或者清除某一位上的值,其返回值是原来位上存储的值
key:在初始状态下所有的位都为 0
offset:可根据业务实际需求设计
value:只能是 0 或者 1
GETBITGETBIT key offset获得key在offffset处的bit值
BITCOUNTBITCOUNT key [start end [BYTE | BIT]]获得key的bit位为1的个数
BITOPBITOP operation destkey key [key …]对多个key 进行逻辑运算后存入destkey中
语法:operation 可以是 AND 、 OR 、 NOT 、 XOR 这四种操作中的任意一种:

BITOP AND destkey key [key …]:对一个或多个key求逻辑与&,并将结果保存到 destkey
BITOP OR destkey key [key …]:对一个或多个key求逻辑或|,并将结果保存到 destkey
BITOP XOR destkey key [key …]:对一个或多个key求逻辑异或^,并将结果保存到destkey
BITOP NOT destkey key:对给定key求逻辑非~,并将结果保存到destkey
除了 NOT 操作之外,其他操作都可以接受一个或多个 key 作为输入
命令的返回值表示存储在目标键中的字符串的大小

示例:

127.0.0.1:6379> setbit user:sign:1000 20220101 1 # 模拟用户签到
(integer) 0
127.0.0.1:6379> setbit user:sign:1000 20220102 1
(integer) 0
127.0.0.1:6379> setbit user:sign:1000 20220104 1
(integer) 0
127.0.0.1:6379> getbit user:sign:1000 20220102 # 判断用户是否签到
(integer) 1
127.0.0.1:6379> bitcount user:sign:1000 # 统计用户签到次数
(integer) 3
127.0.0.1:6379> setbit login_09_19 100 1 # 设置9.19有四位用户登录,9.20有三位用户登录
(integer) 0
127.0.0.1:6379> setbit login_09_19 101 1
(integer) 0
127.0.0.1:6379> setbit login_09_19 102 1
(integer) 0
127.0.0.1:6379> setbit login_09_19 103 1
(integer) 0
127.0.0.1:6379> setbit login_09_20 100 1
(integer) 0
127.0.0.1:6379> setbit login_09_20 101 1
(integer) 0
127.0.0.1:6379> setbit login_09_20 103 1
(integer) 0
127.0.0.1:6379> bitop and login_in_09_19_and_20 login_09_19 login_09_20 # 计算9.19和9.20两天都登陆过的用户
(integer) 13
127.0.0.1:6379> bitcount login_in_09_19_and_20 # 查看9.19和9.20两天都登陆过的用户
(integer) 3
127.0.0.1:6379> bitop or login_in_09_19_or_20 login_09_19 login_09_20 # 计算两天登录过的用户总数
(integer) 13
127.0.0.1:6379> bitcount login_in_09_19_or_20
(integer) 4
127.0.0.1:6379> 

相关文章:

  • Qt使用qBreakpad定位崩溃位置
  • IAR+vscode开发环境搭建,千万别用,当心爱上
  • 一些 Next Generation ABAP Platform 的新语法用例
  • java面向对象思维程序设计开发以及案例 -电梯运行问题对象分析与程序设计(1)
  • vulnhub EMPIRE: BREAKOUT靶机
  • 【Python】PyQt5 Designer工具配置
  • Camera-MTK OpenCamera时序以及耗时
  • SpringCloud链路追踪SkyWalking-第二章-部署搭建及高可用
  • springboot vue3 elementui plus点餐外卖系统源码
  • Node.js阶段学习(一)
  • 一、nacos安装与高可用部署
  • mysql实现删除某一列的重复数据(只留一行或全部删除)
  • 数学建模十大算法01-蒙特卡洛算法(Monte Carlo)
  • 智能家居相关企业达2万余家,湖南智能家居发展将进入快车道
  • java计算机毕业设计高校学生社团管理源码+数据库+系统+lw文档+mybatis+运行部署
  • 【刷算法】求1+2+3+...+n
  • canvas实际项目操作,包含:线条,圆形,扇形,图片绘制,图片圆角遮罩,矩形,弧形文字...
  • ES6语法详解(一)
  • Objective-C 中关联引用的概念
  • Vue组件定义
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 十年未变!安全,谁之责?(下)
  • 王永庆:技术创新改变教育未来
  • 微信小程序--------语音识别(前端自己也能玩)
  • 学习ES6 变量的解构赋值
  • 用quicker-worker.js轻松跑一个大数据遍历
  • 最近的计划
  • 《天龙八部3D》Unity技术方案揭秘
  • 3月27日云栖精选夜读 | 从 “城市大脑”实践,瞭望未来城市源起 ...
  • Java总结 - String - 这篇请使劲喷我
  • 从如何停掉 Promise 链说起
  • ​3ds Max插件CG MAGIC图形板块为您提升线条效率!
  • #基础#使用Jupyter进行Notebook的转换 .ipynb文件导出为.md文件
  • $(function(){})与(function($){....})(jQuery)的区别
  • (175)FPGA门控时钟技术
  • (第27天)Oracle 数据泵转换分区表
  • (第61天)多租户架构(CDB/PDB)
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (算法)求1到1亿间的质数或素数
  • (转)负载均衡,回话保持,cookie
  • (转)关于如何学好游戏3D引擎编程的一些经验
  • .net core Swagger 过滤部分Api
  • .NET/C# 异常处理:写一个空的 try 块代码,而把重要代码写到 finally 中(Constrained Execution Regions)
  • /etc/fstab和/etc/mtab的区别
  • @LoadBalanced 和 @RefreshScope 同时使用,负载均衡失效分析
  • @zabbix数据库历史与趋势数据占用优化(mysql存储查询)
  • [AIGC] MySQL存储引擎详解
  • [BSGS算法]纯水斐波那契数列
  • [C++] 多线程编程-thread::yield()-sleep_for()
  • [HackMyVM]靶场Boxing
  • [javaee基础] 常见的javaweb笔试选择题含答案
  • [JDK工具-2] javap 类文件解析工具-帮助理解class文件,了解Java编译器机制