Redis03---数据类型

1. Redis-key

在redis中无论什么数据类型,在数据库中都是以key-value形式保存,通过进行对Redis-key的操作,来完成对数据库中数据的操作。

下面学习的命令:

  • set key value

  • exists key:判断键是否存在

  • del key:删除键值对

  • move key db:将键值对移动到指定数据库

  • expire key second:设置键值对的过期时间

  • type key:查看value的数据类型

  • ttl key: 查看key的过期剩余时间

    • 当前key没有设置过期时间,所以会返回-1.

    • 当前key有设置过期时间,而且key已经过期,所以会返回-2.

    • 当前key有设置过期时间,且key还没有过期,故会返回key的正常剩余时间.

2. 五大数据类型

2.1 String(字符串)

  1. apppend key value:向指定的key的value后追加字符串

  2. decr/incr key:将指定key的value数值进行+1/-1(仅对于数字)

  3. incrby/decrby key n:按指定的步长对数值进行加减

  4. incrbyfloat key n:为数值加上浮点型数值

  5. strlen key:获取key保存值的字符串长度

  6. getrange key start end:按起止位置获取字符串(闭区间,起止位置都取)

  7. setrange key offset value:用指定的value 替换key中 offset开始的值

  8. getset key value:将给定 key 的值设为 value ,并返回 key 的旧值(old value)。

  9. setnx key value:仅当key不存在时进行set

  10. setex key seconds value:set 键值对并设置过期时间

  11. mset key1 value1 [key2 value2..]:批量set键值对

  12. msetnx key1 value1 [key2 value2..]:批量设置键值对,仅当参数中所有的key都不存在时执行

  13. mget key1 [key2..]:批量获取多个key保存的值

  14. psetex key milliseconds value:和 setex 命令相似,但它以毫秒为单位设置 key 的生存时间

String类似的使用场景:value除了是字符串还可以是数字,用途举例:

  • 计数器

  • 统计多单位的数量:uid:123666:follow 0

  • 粉丝数

  • 对象存储缓存

2.2 List(列表)

Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边);一个列表最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。

正如图Redis中List是可以进行双端操作的,所以命令也就分为了LXXXRXXX两类,有时候L也表示List例如LLEN

  1. LPUSH/RPUSH key value1[value2..]:从左边/右边向列表中PUSH值(一个或者多个)。

  2. LRANGE key start end:获取list 起止元素(索引从左往右 递增)

  3. LPUSHX/RPUSHX key value:向已存在的列名中push值(一个或者多个)

  4. LINSERT key BEFORE|AFTER pivot value:在指定列表元素的前/后 插入value

  5. LLEN key:查看列表长度

  6. LINDEX key index:通过索引获取列表元素

  7. LSET key index value:通过索引为元素设值

  8. LPOP/RPOP key:从最左边/最右边移除值 并返回

  9. RPOPLPUSH source destination:将列表的尾部(右)最后一个值弹出,并返回,然后加到另一个列表的头部

  10. LTRIM key start end:通过下标截取指定范围内的列表

  11. LREM key count value:List中是允许value重复的 count > 0:从头部开始搜索 然后删除指定的value 至多删除count个 count < 0:从尾部开始搜索… count = 0:删除列表中所有的指定value。

  12. BLPOP/BRPOP key1[key2] timout:移出并获取列表的第一个/最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止

  13. BRPOPLPUSH source destination timeout:和RPOPLPUSH功能相同,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。

测试

---------------------------LPUSH---RPUSH---LRANGE--------------------------------

127.0.0.1:6379> LPUSH mylist k1 # LPUSH mylist=>{1}
(integer) 1
127.0.0.1:6379> LPUSH mylist k2 # LPUSH mylist=>{2,1}
(integer) 2
127.0.0.1:6379> RPUSH mylist k3 # RPUSH mylist=>{2,1,3}
(integer) 3
127.0.0.1:6379> get mylist # 普通的get是无法获取list值的
(error) WRONGTYPE Operation against a key holding the wrong kind of value
127.0.0.1:6379> LRANGE mylist 0 2 # LRANGE 获取起止位置范围内的元素
1) "k2"
2) "k1"
3) "k3"
127.0.0.1:6379> LRANGE mylist 0 1
1) "k2"
2) "k1"
127.0.0.1:6379> LRANGE mylist 0 -1 # 获取全部元素
1) "k2"
2) "k1"
3) "k3"

---------------------------LPUSHX---RPUSHX-----------------------------------

127.0.0.1:6379> LPUSHX list v1 # list不存在 LPUSHX失败
(integer) 0
127.0.0.1:6379> LPUSHX mylist k4 k5 # 向mylist中 左边 PUSH k4 k5
(integer) 5
127.0.0.1:6379> LRANGE mylist 0 -1
1) "k5"
2) "k4"
3) "k2"
4) "k1"
5) "k3"

---------------------------LINSERT--LLEN--LINDEX--LSET----------------------------

127.0.0.1:6379> LINSERT mylist after k2 ins_key1 # 在k2元素后 插入ins_key1
(integer) 6
127.0.0.1:6379> LRANGE mylist 0 -1
1) "k5"
2) "k4"
3) "k2"
4) "ins_key1"
5) "k1"
6) "k3"
127.0.0.1:6379> LLEN mylist # 查看mylist的长度
(integer) 6
127.0.0.1:6379> LINDEX mylist 3 # 获取下标为3的元素
"ins_key1"
127.0.0.1:6379> LINDEX mylist 0
"k5"
127.0.0.1:6379> LSET mylist 3 k6 # 将下标3的元素 set值为k6
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "k5"
2) "k4"
3) "k2"
4) "k6"
5) "k1"
6) "k3"

---------------------------LPOP--RPOP--------------------------

127.0.0.1:6379> LPOP mylist # 左侧(头部)弹出
"k5"
127.0.0.1:6379> RPOP mylist # 右侧(尾部)弹出
"k3"

---------------------------RPOPLPUSH--------------------------

127.0.0.1:6379> LRANGE mylist 0 -1
1) "k4"
2) "k2"
3) "k6"
4) "k1"
127.0.0.1:6379> RPOPLPUSH mylist newlist # 将mylist的最后一个值(k1)弹出,加入到newlist的头部
"k1"
127.0.0.1:6379> LRANGE newlist 0 -1
1) "k1"
127.0.0.1:6379> LRANGE mylist 0 -1
1) "k4"
2) "k2"
3) "k6"

---------------------------LTRIM--------------------------

127.0.0.1:6379> LTRIM mylist 0 1 # 截取mylist中的 0~1部分
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "k4"
2) "k2"

# 初始 mylist: k2,k2,k2,k2,k2,k2,k4,k2,k2,k2,k2
---------------------------LREM--------------------------

127.0.0.1:6379> LREM mylist 3 k2 # 从头部开始搜索 至多删除3个 k2
(integer) 3
# 删除后:mylist: k2,k2,k2,k4,k2,k2,k2,k2

127.0.0.1:6379> LREM mylist -2 k2 #从尾部开始搜索 至多删除2个 k2
(integer) 2
# 删除后:mylist: k2,k2,k2,k4,k2,k2


---------------------------BLPOP--BRPOP--------------------------

mylist: k2,k2,k2,k4,k2,k2
newlist: k1

127.0.0.1:6379> BLPOP newlist mylist 30 # 从newlist中弹出第一个值,mylist作为候选
1) "newlist" # 弹出
2) "k1"
127.0.0.1:6379> BLPOP newlist mylist 30
1) "mylist" # 由于newlist空了 从mylist中弹出
2) "k2"
127.0.0.1:6379> BLPOP newlist 30
(30.10s) # 超时了

127.0.0.1:6379> BLPOP newlist 30 # 我们连接另一个客户端向newlist中push了test, 阻塞被解决。
1) "newlist"
2) "test"
(12.54s)

小结

  • list实际上是一个链表,before Node after , left, right 都可以插入值

  • 如果key不存在,则创建新的链表

  • 如果key存在,新增内容

  • 如果移除了所有值,空链表,也代表不存在

  • 在两边插入或者改动值,效率最高!修改中间元素,效率相对较低

应用

消息队列(Lpush Rpop)

栈(Lpush Lpop)

2.3 Set(集合)

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

  • Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)

  • 集合中最大的成员数为 2^32 - 1

  1. SADD key member1[member2..]:向集合中无序增加一个/多个成员

  2. SCARD key:获取集合的成员数

  3. SMEMBERS key:返回集合中所有的成员

  4. SISMEMBER key member:查询member元素是否是集合的成员,结果是无序的

  5. SRANDMEMBER key [count]:随机返回集合中count个成员,count缺省值为1

  6. SPOP key [count]:随机移除并返回集合中count个成员,count缺省值为1

  7. SMOVE source destination member:将source集合的成员member移动到destination集合

  8. SREM key member1[member2..]:移除集合中一个/多个成员

  9. SDIFF key1[key2..]:返回所有集合的差集 key1- key2 - …

  10. SDIFFSTORE destination key1[key2..]:在SDIFF的基础上,将结果保存到集合中(覆盖)。不能保存到其他类型key

  11. SINTER key1 [key2..]:返回所有集合的交集

  12. SINTERSTORE destination key1[key2..]:在SINTER的基础上,存储结果到集合中。覆盖

  13. SUNION key1 [key2..]:返回所有集合的并集

  14. SUNIONSTORE destination key1 [key2..]:在SUNION的基础上,存储结果到及和张。覆盖

  15. SSCAN KEY [MATCH pattern] [COUNT count]:在大量数据环境下,使用此命令遍历集合中元素,每次遍历部分

测试

---------------SADD--SCARD--SMEMBERS--SISMEMBER--------------------

127.0.0.1:6379> SADD myset m1 m2 m3 m4 # 向myset中增加成员 m1~m4
(integer) 4
127.0.0.1:6379> SCARD myset # 获取集合的成员数目
(integer) 4
127.0.0.1:6379> smembers myset # 获取集合中所有成员
1) "m4"
2) "m3"
3) "m2"
4) "m1"
127.0.0.1:6379> SISMEMBER myset m5 # 查询m5是否是myset的成员
(integer) 0 # 不是,返回0
127.0.0.1:6379> SISMEMBER myset m2
(integer) 1 # 是,返回1

---------------------SRANDMEMBER--SPOP----------------------------------

127.0.0.1:6379> SRANDMEMBER myset 3 # 随机返回3个成员
1) "m2"
2) "m3"
3) "m4"
127.0.0.1:6379> SRANDMEMBER myset # 随机返回1个成员
"m3"
127.0.0.1:6379> SPOP myset 2 # 随机移除并返回2个成员
1) "m1"
2) "m4"
# 将set还原到{m1,m2,m3,m4}

---------------------SMOVE--SREM----------------------------------------

127.0.0.1:6379> SMOVE myset newset m3 # 将myset中m3成员移动到newset集合
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "m4"
2) "m2"
3) "m1"
127.0.0.1:6379> SMEMBERS newset
1) "m3"
127.0.0.1:6379> SREM newset m3 # 从newset中移除m3元素
(integer) 1
127.0.0.1:6379> SMEMBERS newset
(empty list or set)

# 下面开始是多集合操作,多集合操作中若只有一个参数默认和自身进行运算
# setx=>{m1,m2,m4,m6}, sety=>{m2,m5,m6}, setz=>{m1,m3,m6}

-----------------------------SDIFF------------------------------------

127.0.0.1:6379> SDIFF setx sety setz # 等价于setx-sety-setz
1) "m4"
127.0.0.1:6379> SDIFF setx sety # setx - sety
1) "m4"
2) "m1"
127.0.0.1:6379> SDIFF sety setx # sety - setx
1) "m5"


-------------------------SINTER---------------------------------------
# 共同关注(交集)

127.0.0.1:6379> SINTER setx sety setz # 求 setx、sety、setx的交集
1) "m6"
127.0.0.1:6379> SINTER setx sety # 求setx sety的交集
1) "m2"
2) "m6"

-------------------------SUNION---------------------------------------

127.0.0.1:6379> SUNION setx sety setz # setx sety setz的并集
1) "m4"
2) "m6"
3) "m3"
4) "m2"
5) "m1"
6) "m5"
127.0.0.1:6379> SUNION setx sety # setx sety 并集
1) "m4"
2) "m6"
3) "m2"
4) "m1"
5) "m5"

2.4 Hash(哈希)

  • Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象

  • Set就是一种简化的Hash,只变动key,而value使用默认值填充。可以将一个Hash表作为一个对象进行存储,表中存放对象的信息

  1. HSET key field value:将哈希表 key 中的字段 field 的值设为 value 。重复设置同一个field会覆盖,返回0

  2. HMSET key field1 value1 [field2 value2..]:同时将多个 field-value (域-值)对设置到哈希表 key 中。

  3. HSETNX key field value:只有在字段 field 不存在时,设置哈希表字段的值。

  4. HEXISTS key field:查看哈希表 key 中,指定的字段是否存在。

  5. HGET key field value:获取存储在哈希表中指定字段的值

  6. HMGET key field1 [field2..]:获取所有给定字段的值

  7. HGETALL key:获取在哈希表key 的所有字段和值

  8. HKEYS key:获取哈希表key中所有的字段

  9. HLEN key:获取哈希表中字段的数量

  10. HVALS key:获取哈希表中所有值

  11. HDEL key field1 [field2..]:删除哈希表key中一个/多个field字段

  12. HINCRBY key field n:为哈希表 key 中的指定字段的整数值加上增量n,并返回增量后结果 一样只适用于整数型字段

  13. HINCRBYFLOAT key field n:为哈希表 key 中的指定字段的浮点数值加上增量 n。

  14. HSCAN key cursor [MATCH pattern] [COUNT count]:迭代哈希表中的键值对。

测试

------------------------HSET--HMSET--HSETNX----------------
127.0.0.1:6379> HSET studentx name sakura # 将studentx哈希表作为一个对象,设置name为sakura
(integer) 1
127.0.0.1:6379> HSET studentx name qc # 重复设置field进行覆盖,并返回0
(integer) 0
127.0.0.1:6379> HSET studentx age 24 # 设置studentx的age为20
(integer) 1
127.0.0.1:6379> HMSET studentx sex 1 tel 15623667886 # 设置sex为1,tel为15623667886
OK
127.0.0.1:6379> HSETNX studentx name qc # HSETNX 设置已存在的field
(integer) 0 # 失败
127.0.0.1:6379> HSETNX studentx email 12345@qq.com
(integer) 1 # 成功

----------------------HEXISTS--------------------------------
127.0.0.1:6379> HEXISTS studentx name # name字段在studentx中是否存在
(integer) 1 # 存在
127.0.0.1:6379> HEXISTS studentx addr
(integer) 0 # 不存在

-------------------HGET--HMGET--HGETALL-----------
127.0.0.1:6379> HGET studentx name # 获取studentx中name字段的value
"qc"
127.0.0.1:6379> HMGET studentx name age tel # 获取studentx中name、age、tel字段的value
1) "qc"
2) "24"
3) "15623667886"
127.0.0.1:6379> HGETALL studentx # 获取studentx中所有的field及其value
 1) "name"
 2) "qc"
 3) "age"
 4) "24"
 5) "sex"
 6) "1"
 7) "tel"
 8) "15623667886"
 9) "email"
10) "12345@qq.com"


--------------------HKEYS--HLEN--HVALS--------------
127.0.0.1:6379> HKEYS studentx # 查看studentx中所有的field
1) "name"
2) "age"
3) "sex"
4) "tel"
5) "email"
127.0.0.1:6379> HLEN studentx # 查看studentx中的字段数量
(integer) 5
127.0.0.1:6379> HVALS studentx # 查看studentx中所有的value
1) "qc"
2) "24"
3) "1"
4) "15623667886"
5) "12345@qq.com"

-------------------------HDEL--------------------------
127.0.0.1:6379> HDEL studentx sex tel # 删除studentx 中的sex、tel字段
(integer) 2
127.0.0.1:6379> HKEYS studentx
1) "name"
2) "age"
3) "email"

-------------HINCRBY--HINCRBYFLOAT------------------------
127.0.0.1:6379> HINCRBY studentx age 1 # studentx的age字段数值+1
(integer) 25
127.0.0.1:6379> HINCRBY studentx name 1 # 非整数字型字段不可用
(error) ERR hash value is not an integer
127.0.0.1:6379> HINCRBYFLOAT studentx weight 0.6 # weight字段增加0.6
"90.8"

2.5 Zset(有序集合)

  • 不同的是每个元素都会关联一个double类型的分数(score)。redis正是通过分数来为集合中的成员进行从小到大的排序。

  • score相同:按字典顺序排序

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

  1. ZADD key score member1 [score2 member2]:向有序集合添加一个或多个成员,或者更新已存在成员的分数

  2. ZCARD key:获取有序集合的成员数

  3. ZCOUNT key min max:计算在有序集合中指定区间score的成员数

  4. ZINCRBY key n member:有序集合中对指定成员的分数加上增量 n

  5. ZSCORE key member:返回有序集中,成员的分数值

  6. ZRANK key member:返回有序集合中指定成员的索引

  7. ZRANGE key start end:通过索引区间返回有序集合成指定区间内的成员

  8. ZRANGEBYLEX key min max:通过字典区间返回有序集合的成员

  9. ZRANGEBYSCORE key min max:通过分数返回有序集合指定区间内的成员-inf 和 +inf分别表示最小最大值,只支持开区间()

  10. ZLEXCOUNT key min max:在有序集合中计算指定字典区间内成员数量

  11. ZREM key member1 [member2..]:移除有序集合中一个/多个成员

  12. ZREMRANGEBYLEX key min max:移除有序集合中给定的字典区间的所有成员

  13. ZREMRANGEBYRANK key start stop:移除有序集合中给定的排名区间的所有成员

  14. ZREMRANGEBYSCORE key min max:移除有序集合中给定的分数区间的所有成员

  15. ZREVRANGE key start end:返回有序集中指定区间内的成员,通过索引,分数从高到底

  16. ZREVRANGEBYSCORRE key max min:返回有序集中指定分数区间内的成员,分数从高到低排序

  17. ZREVRANGEBYLEX key max min:返回有序集中指定字典区间内的成员,按字典顺序倒序

  18. ZREVRANK key member:返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序

  19. ZINTERSTORE destination numkeys key1 [key2 ..]:计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中,numkeys:表示参与运算的集合数,将score相加作为结果的score

  20. ZUNIONSTORE destination numkeys key1 [key2..]:计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中

  21. ZSCAN key cursor [MATCH pattern\] [COUNT count]:迭代有序集合中的元素(包括元素成员和元素分值)

测试

-------------------ZADD--ZCARD--ZCOUNT--------------
127.0.0.1:6379> ZADD myzset 1 m1 2 m2 3 m3 # 向有序集合myzset中添加成员m1 score=1 以及成员m2 score=2,m3 score=3
(integer) 3
127.0.0.1:6379> ZCARD myzset # 获取有序集合的成员数
(integer) 3
127.0.0.1:6379> ZCOUNT myzset 0 2 # 获取score在 [0,2]区间的成员数量
(integer) 2
127.0.0.1:6379> ZRANGE myzset 0 -1 # 获取全部成员
1) "m1"
2) "m2"
3) "m3"

----------------ZINCRBY--ZSCORE--------------------------
127.0.0.1:6379> ZINCRBY myzset 5 m2 # 将成员m2的score +5
"7"
127.0.0.1:6379> ZSCORE myzset m1 # 获取成员m1的score
"1"
127.0.0.1:6379> ZSCORE myzset m3
"3"

--------------ZRANK--ZRANGE-----------------------------------
127.0.0.1:6379> ZRANK myzset m1 # 获取成员m1的索引,索引按照score排序,score相同索引值按字典顺序顺序增加
(integer) 0
127.0.0.1:6379> ZRANK myzset m2
(integer) 2
127.0.0.1:6379> ZRANGE myzset 0 1 # 获取索引在 0~1的成员
1) "m1"
2) "m3"
127.0.0.1:6379> ZRANGE myzset 0 -1 # 获取全部成员
1) "m1"
2) "m3"
3) "m2"

#testset=>{abc,add,amaze,apple,back,java,redis} score均为0
------------------ZRANGEBYLEX---------------------------------
127.0.0.1:6379> ZRANGEBYLEX testset - + # 返回所有成员
1) "abc"
2) "add"
3) "amaze"
4) "apple"
5) "back"
6) "java"
7) "redis"
127.0.0.1:6379> ZRANGEBYLEX testset - + LIMIT 0 3 # 分页 按索引显示查询结果的 0,1,2条记录
1) "abc"
2) "add"
3) "amaze"
127.0.0.1:6379> ZRANGEBYLEX testset - + LIMIT 3 3 # 显示 3,4,5条记录
1) "apple"
2) "back"
3) "java"
127.0.0.1:6379> ZRANGEBYLEX testset (- [apple # 显示 (-,apple] 区间内的成员
1) "abc"
2) "add"
3) "amaze"
4) "apple"
127.0.0.1:6379> ZRANGEBYLEX testset [apple [java # 显示 [apple,java]字典区间的成员
1) "apple"
2) "back"
3) "java"

-----------------------ZRANGEBYSCORE---------------------
127.0.0.1:6379> ZRANGEBYSCORE myzset 1 10 # 返回score在 [1,10]之间的的成员
1) "m1"
2) "m3"
3) "m2"
127.0.0.1:6379> ZRANGEBYSCORE myzset 1 5
1) "m1"
2) "m3"

--------------------ZLEXCOUNT-----------------------------
127.0.0.1:6379> ZLEXCOUNT testset - +
(integer) 7
127.0.0.1:6379> ZLEXCOUNT testset [apple [java
(integer) 3

------------------ZREM--ZREMRANGEBYLEX--ZREMRANGBYRANK--ZREMRANGEBYSCORE--------------------------------
127.0.0.1:6379> ZREM testset abc # 移除成员abc
(integer) 1
127.0.0.1:6379> ZREMRANGEBYLEX testset [apple [java # 移除字典区间[apple,java]中的所有成员
(integer) 3
127.0.0.1:6379> ZREMRANGEBYRANK testset 0 1 # 移除排名0~1的所有成员
(integer) 2
127.0.0.1:6379> ZREMRANGEBYSCORE myzset 0 3 # 移除score在 [0,3]的成员
(integer) 2


# testset=> {abc,add,apple,amaze,back,java,redis} score均为0
# myzset=> {(m1,1),(m2,2),(m3,3),(m4,4),(m7,7),(m9,9)}
----------------ZREVRANGE--ZREVRANGEBYSCORE--ZREVRANGEBYLEX-----------
127.0.0.1:6379> ZREVRANGE myzset 0 3 # 按score递减排序,然后按索引,返回结果的 0~3
1) "m9"
2) "m7"
3) "m4"
4) "m3"
127.0.0.1:6379> ZREVRANGE myzset 2 4 # 返回排序结果的 索引的2~4
1) "m4"
2) "m3"
3) "m2"
127.0.0.1:6379> ZREVRANGEBYSCORE myzset 6 2 # 按score递减顺序 返回集合中分数在[2,6]之间的成员
1) "m4"
2) "m3"
3) "m2"
127.0.0.1:6379> ZREVRANGEBYLEX testset [java (add # 按字典倒序 返回集合中(add,java]字典区间的成员
1) "java"
2) "back"
3) "apple"
4) "amaze"

-------------------------ZREVRANK------------------------------
127.0.0.1:6379> ZREVRANK myzset m7 # 按score递减顺序,返回成员m7索引
(integer) 1
127.0.0.1:6379> ZREVRANK myzset m2
(integer) 4


# mathscore=>{(xm,90),(xh,95),(xg,87)} 小明、小红、小刚的数学成绩
# enscore=>{(xm,70),(xh,93),(xg,90)} 小明、小红、小刚的英语成绩
-------------------ZINTERSTORE--ZUNIONSTORE-----------------------------------
127.0.0.1:6379> ZINTERSTORE sumscore 2 mathscore enscore # 将mathscore enscore进行合并 结果存放到sumscore
(integer) 3
127.0.0.1:6379> ZRANGE sumscore 0 -1 withscores # 合并后的score是之前集合中所有score的和
1) "xm"
2) "160"
3) "xg"
4) "177"
5) "xh"
6) "188"

127.0.0.1:6379> ZUNIONSTORE lowestscore 2 mathscore enscore AGGREGATE MIN # 取两个集合的成员score最小值作为结果的
(integer) 3
127.0.0.1:6379> ZRANGE lowestscore 0 -1 withscores
1) "xm"
2) "70"
3) "xg"
4) "87"
5) "xh"
6) "93"

应用案例

  • set排序 存储班级成绩表 工资表排序
  • 普通消息,1.重要消息 2.带权重进行判断
  • 排行榜应用实现,取Top N测试

3. 三种特殊数据类型

3.1 Geospatial(地理位置)

使用经纬度定位地理坐标并用一个有序集合zset保存,所以zset命令也可以使用

有效经纬度

  • 有效的经度从-180度到180度。

  • 有效的纬度从-85.05112878度到85.05112878度。

指定单位的参数 unit 必须是以下单位的其中一个

  • m 表示单位为米。

  • km 表示单位为千米。

  • mi 表示单位为英里。

  • ft 表示单位为英尺。

关于GEORADIUS的参数

  • 通过georadius就可以完成 附近的人功能

  • withcoord:带上坐标

  • withdist:带上距离,单位与半径单位相同

  • COUNT n : 只显示前n个(按距离递增排序)

命令

  1. geoadd key longitud(经度) latitude(纬度) member [..]:将具体经纬度的坐标存入一个有序集合

  2. geopos key member [member..]:获取集合中的一个/多个成员坐标

  3. geodist key member1 member2 [unit]:返回两个给定位置之间的距离。默认以米作为单位。

  4. georadius key longitude latitude radius m|km|mi|ft [WITHCOORD][WITHDIST] [WITHHASH] [COUNT count]:以给定的经纬度为中心, 返回集合包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。

  5. GEORADIUSBYMEMBER key member radius...:功能与GEORADIUS相同,只是中心位置不是具体的经纬度,而是使用结合中已有的成员作为中心点。

  6. geohash key member1 [member2..]:返回一个或多个位置元素的Geohash表示。使用Geohash位置52点整数编码。

测试

----------------geoadd---------------------
# 添加地理位置
# 规则:两级无法添加,我们一般会下载城市数据,通过Java程序导入
127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing 121.47 31.23 shanghai 118.76 32.04 nanjing
(integer) 3
127.0.0.1:6379> geoadd china:city 113.28 23.12 guangzhou 117.19 39.12 tianjin 114.08 22.54 shenzheng
(integer) 3

----------------georadius---------------------
127.0.0.1:6379> GEORADIUS china:city 120 30 500 km withcoord withdist # 查询经纬度(120,30)坐标500km半径内的成员
1) 1) "hangzhou"
   2) "29.4151"
   3) 1) "120.20000249147415"
      2) "30.199999888333501"
2) 1) "shanghai"
   2) "205.3611"
   3) 1) "121.40000134706497"
      2) "31.400000253193539"
     
------------geohash---------------------------
127.0.0.1:6379> geohash china:city yichang shanghai # 获取成员经纬坐标的geohash表示
1) "wmrjwbr5250"
2) "wtw6ds0y300"

3.2 Hyperloglog(基数统计)

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

  • 花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。

  • 因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。

  • 其底层使用string数据类型

【什么是基数?】--->数据集中不重复的元素的个数

【应用场景】--->网页的访问量(UV):一个用户多次访问,也只能算作一个人

命令

  • PFADD key element1 [elememt2..]:添加指定元素到 HyperLogLog 中

  • PFCOUNT key [key]:返回给定 HyperLogLog 的基数估算值。

  • PFMERGE destkey sourcekey [sourcekey..]:将多个 HyperLogLog 合并为一个 HyperLogLog

测试

----------PFADD--PFCOUNT---------------------
127.0.0.1:6379> PFADD myelemx a b c d e f g h i j k # 添加元素
(integer) 1
127.0.0.1:6379> type myelemx # hyperloglog底层使用String
string
127.0.0.1:6379> PFCOUNT myelemx # 估算myelemx的基数
(integer) 11
127.0.0.1:6379> PFADD myelemy i j k z m c b v p q s
(integer) 1
127.0.0.1:6379> PFCOUNT myelemy
(integer) 11

----------------PFMERGE-----------------------
127.0.0.1:6379> PFMERGE myelemz myelemx myelemy # 合并myelemx和myelemy 成为myelemz
OK
127.0.0.1:6379> PFCOUNT myelemz # 估算基数
(integer) 17

【说明】

  • 如果允许容错,那么一定可以使用Hyperloglog !

  • 如果不允许容错,就使用set或者自己的数据类型即可 !

3.3 BitMaps(位图)

  • 使用位存储,信息状态只有 0 和 1

  • Bitmap是一串连续的2进制数字(0或1),每一位所在的位置为偏移(offset),在bitmap上可执行AND,OR,XOR,NOT以及其它位操作。

  • 应用场景:签到统计、状态统计

命令

  • setbit key offset value:为指定key的offset位设置值

  • getbit key offset:获取offset位的值

  • bitcount key [start end]:统计字符串被设置为1的bit数,也可以指定统计范围按字节

  • bitop operration destkey key[key..]:对一个或多个保存二进制位的字符串 key 进行位元操作,并将结果保存到 destkey 上。

  • BITPOS key bit [start] [end]:返回字符串里面第一个被设置为1或者0的bit位。start和end只能按字节,不能按位

测试

------------setbit--getbit--------------
127.0.0.1:6379> setbit sign 0 1 # 设置sign的第0位为 1 
(integer) 0
127.0.0.1:6379> setbit sign 2 1 # 设置sign的第2位为 1  不设置默认 是0
(integer) 0
127.0.0.1:6379> setbit sign 3 1
(integer) 0
127.0.0.1:6379> setbit sign 5 1
(integer) 0
127.0.0.1:6379> type sign
string

127.0.0.1:6379> getbit sign 2 # 获取第2位的数值
(integer) 1
127.0.0.1:6379> getbit sign 3
(integer) 1
127.0.0.1:6379> getbit sign 4 # 未设置默认是0
(integer) 0

-----------bitcount----------------------------
127.0.0.1:6379> BITCOUNT sign # 统计sign中为1的位数
(integer) 4
posted @ 2021-08-18 11:31  qi_chao  阅读(40)  评论(0编辑  收藏  举报