![](https://i-blog.csdnimg.cn/blog_migrate/552966e50102fec8d1980e1242ce86ed.jpeg)
Redis学习笔记_02
本文基于B站UP主【遇见狂神说】视频教程 【Redis最新超详细版教程通俗易懂】进行整理/记录,仅用于个人学习交流使用
狂神主页:https://space.bilibili.com/95256449
视频地址:https://www.bilibili.com/video/BV1S54y1R7SB
Redis官方中文文档:http://www.redis.cn/
参考博客:https://blog.csdn.net/DDDDeng_/article/details/108118544
参考博客:https://blog.csdn.net/lisen01070107/article/details/108507798
目录标题
三、五大数据类型
Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。
Redis官方命令中文文档:http://www.redis.cn/commands.html
0.[前置] Redis-key
一些命令:
exists key:判断键是否存在
del key:删除键值对
move key db:将键值对移动到指定数据库
expire key second:设置键值对的过期时间,单位是秒
ttl key:查看当前key剩余的过期时间
type key:查看value的数据类型
关于TTL命令
Redis的key,通过TTL命令返回key的过期时间,一般来说有3种:
- 当前key没有设置过期时间,所以会返回-1.
- 当前key有设置过期时间,而且key已经过期,所以会返回-2.
- 当前key有设置过期时间,且key还没有过期,故会返回key的正常剩余时间.
1.String(字符串)
基本用法
############################################################
127 .0.0.1:6379> set name lisen # 设置值
127 .0.0.1:6379> get lisen # 获得值
127 .0.0.1:6379> keys * # 获得所有的key
127 .0.0.1:6379> EXISTS lisen # 判断某一个key是否存在
(integer) 1
#追加字符串,如果当前key不存在,就相当于setkey
127 .0.0.1:6379> APPEND lisen "hehe" # 9就是name的值的长度
(integer) 9
127 .0.0.1:6379> get lisen
"lisenhehe"
127 .0.0.1:6379> STRLEN key1 # 获取字符串的长度!
(integer) 9
############################################################
# i++
# 步长 i+=
127 .0.0.1:6379> set views 0 # 初始浏览量为 0
OK
127 .0.0.1:6379> get views
"0"
127 .0.0.1:6379> incr views # 自增 1 浏览量变为 1
(integer) 1
127 .0.0.1:6379> incr views
(integer) 2
127 .0.0.1:6379> get viewsg
"2"
127 .0.0.1:6379> decr views # 自减 1 浏览量-1
(integer) 1
127 .0.0.1:6379> decr views
(integer) 0
127 .0.0.1:6379> decr views
(integer) -1
127 .0.0.1:6379> get views
"-1"
127 .0.0.1:6379> INCRBY views 10 # 可以设置步长,指定增量!
(integer) 9
127 .0.0.1:6379> INCRBY views 10
(integer) 19
127 .0.0.1:6379> DECRBY views 5
(integer) 14
############################################################
字符串范围range
替换 SETRANGE
127.0.0.1:6379[13]> set key1 hello,lisen # 设置 key1 的值
OK
127.0.0.1:6379[13]> GETRANGE key1 0 3 # 截取字符串 [0,3]
"hell"
127.0.0.1:6379[13]> GETRANGE key1 0 -1 # 获取全部的字符串 和 get key是一样的
"hello,lisen"
127.0.0.1:6379[13]> SETRANGE key1 1 xx #替换指定位置开始的字符串!写多少长度的就换多少长度的
127.0.0.1:6379[13]> SETRANGE key1 0 l
(integer) 11
127.0.0.1:6379[13]> get key1
"lello,lisen"
127.0.0.1:6379[13]> SETRANGE key1 0 lllllll
(integer) 11
127.0.0.1:6379[13]> get key1
"lllllllisen"
setex 设置过期时间
setnx 不存在设置
setex (set with expire) # 设置过期时间
setnx (set if not exist) # 不存在在设置(在分布式锁中会常常使用!)
ttl key # 查看过期时间
127.0.0.1:6379[13]> SETEX key1 10 lisen # key1 的值为 lisen,10秒后过期
OK
127 .0.0.1:6379[13]> setnx mykey "redis" # 如果mykey 不存在,创建mykey
mset 设置多个值
mget 获取多个值
# 同时设置多个值
# mset
127.0.0.1:6379[13]> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379[13]> keys *
1) "view"
2) "k3"
3) "k2"
4) "k1"
# 同时获取多个值
# mget
127 .0.0.1:6379> mget k1 k2 k3
1 ) "v1"
2 ) "v2"
3 ) "v3"
# 对象
127.0.0.1:6379[3]> set user:1 {name:zhangsan,age:3}
OK
127.0.0.1:6379[3]> keys *
1) "user:1"
127.0.0.1:6379[3]> get user:1
"{name:zhangsan,age:3}"
# user:{id}:{filed} 在 Redis中完全OK
# 一个巧妙的设计
127.0.0.1:6379[3]> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379[3]> mget user:1:name user:1:age
1) "zhangsan"
2) "2"
getset
127.0.0.1:6379[3]> getset db redis #如果不存在则返回uil,并设置为新值
(nil)
127.0.0.1:6379[3]> get db
"redis"
127.0.0.1:6379[3]> getset db mongodb #如果存在则返回旧值,并设置新值
"redis"
127.0.0.1:6379[3]> get db
"mongodb"
String类似的使用场景:value除了是字符串还可以是数字,用途举例:
- 计数器
- 统计多单位的数量:uid:123666:follow 0
- 粉丝数
- 对象存储缓存
2.List(列表)
Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)
一个列表最多可以包含 232 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。
首先我们列表,可以经过规则定义将其变为队列、栈、双端队列等。
正如图Redis中List是可以进行双端操作的,所以命令也就分为了LXXX和RLLL两类,有时候L也表示List例如LLEN
基础命令讲解:
LPUSH:将一个或多个值放到列表的头部(左边)
RPUSH:将一个或多个值放到列表的尾部(右边)
127.0.0.1:6379> flushd
(error) ERR unknown command 'flushd'
127.0.0.1:6379> flushall
OK
127.0.0.1:6379> LPUSH list one #将一个或多个值放到列表的头部(左边)
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> RPUSH list four #将一个或多个值放到列表的尾部(右边)
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "four"
lrange:查看一定范围内的元素
Lpop:移除左边的值
Rpop:移除右边的值
Llen:计算长度
Lindex:按照下标索引
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "four"
127.0.0.1:6379> Lpop list
"three"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "four"
127.0.0.1:6379> Rpop list
"four"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> lindex list 1
"one"
127.0.0.1:6379> Llen list
(integer) 2
lrem:移除指定个数的值
127.0.0.1:6379> lpush list two # list里面可以存放多个相同的值
(integer) 3
127.0.0.1:6379> lpush list two
(integer) 4
127.0.0.1:6379> lpush list two
(integer) 5
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "two"
3) "two"
4) "two"
5) "one"
127.0.0.1:6379> lrem list 1 one # 移除一个 one
(integer) 1
127.0.0.1:6379> lrem list 2 two # 移除两个 two
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "two"
# 如果存在多个符合条件的情况,按照索引值从1到n查找进行移除
127.0.0.1:6379> lrange list 0 -1
1) "ttt"
2) "one"
3) "one"
4) "one"
5) "tt"
6) "two"
7) "one"
8) "one"
127.0.0.1:6379> lrem list 2 one
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "ttt"
2) "one"
3) "tt"
4) "two"
5) "one"
6) "one"
ltrim:按照索引截断元素
rpoplpush:将列表最后一个元素弹出并返回,然后添加到另一个列表中
127.0.0.1:6379> lrange list 0 -1
1) "ttt"
2) "one"
3) "tt"
4) "two"
5) "one"
6) "one"
127.0.0.1:6379> ltrim list 0 3
OK
127.0.0.1:6379> lrange list 0 -1
1) "ttt"
2) "one"
3) "tt"
4) "two"
127.0.0.1:6379> rpoplpush list list2
"two"
127.0.0.1:6379> lrange list 0 -1
1) "ttt"
2) "one"
3) "tt"
127.0.0.1:6379> lrange list2 0 -1
1) "two"
lest:按照下标将列表中的值替换,不存在则保存
Linsert:在指定元素的左边/右边插入
127.0.0.1:6379> lrange list2 0 -1
1) "two"
127.0.0.1:6379> lset list2 0 three
OK
127.0.0.1:6379> lrange list2 0 -1
1) "three"
127.0.0.1:6379> linsert list2 before three five #在 three 左边插入 five
(integer) 2
127.0.0.1:6379> linsert list2 after three six #在 three 右边插入 six
(integer) 3
127.0.0.1:6379> lrange list2 0 -1
1) "five"
2) "three"
3) "six"
命令 | 描述 |
---|---|
LPUSH/RPUSH key value1[value2…] | 从左边/右边向列表中PUSH值(一个或者多个)。 |
LRANGE key start end | 获取list 起止元素 ==(索引从左往右 递增)== |
LPUSHX/RPUSHX key value | 向已存在的列名中push值(一个或者多个) |
LINSERT key BEFORE | AFTER pivot value |
LLEN key | 查看列表长度 |
LINDEX key index | 通过索引获取列表元素 |
LSET key index value | 通过索引为元素设值 |
LPOP/RPOP key | 从最左边/最右边移除值 并返回 |
RPOPLPUSH source destination | 将列表的尾部(右)最后一个值弹出,并返回,然后加到另一个列表的头部 |
LTRIM key start end | 通过下标截取指定范围内的列表 |
LREM key count value | List中是允许value重复的 count > 0:从头部开始搜索 然后删除指定的value 至多删除count个 count < 0:从尾部开始搜索… count = 0:删除列表中所有的指定value。 |
BLPOP/BRPOP key1[key2] timout | 移出并获取列表的第一个/最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
BRPOPLPUSH source destination timeout | 和RPOPLPUSH功能相同,如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。 |
小结:
- list实际上是一个链表,before Node after , left, right 都可以插入值
- 如果key不存在,则创建新的链表
- 如果key存在,新增内容
- 如果移除了所有值,空链表,也代表不存在
- 在两边插入或者改动值,效率最高!修改中间元素,效率相对较低
应用:
消息排队!消息队列(Lpush Rpop),栈(Lpush Lpop)
3.Set(集合)
Redis的Set是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
Redis中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。
集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。
命令介绍
SADD key member1[member2…] 向集合中无序增加一个/多个成员
SCARD key 获取集合的成员数
SMEMBERS key 返回集合中所有的成员
SISMEMBER key member 查询member元素是否是集合的成员,结果是无序的
127.0.0.1:6379> sadd set 001 002 003 004 005
(integer) 5
127.0.0.1:6379> smembers set
1) "004"
2) "003"
3) "002"
4) "001"
5) "005"
127.0.0.1:6379> sismember set 001
(integer) 1
127.0.0.1:6379> sismember set 005
(integer) 1
127.0.0.1:6379> sismember set 006
(integer) 0
scard:获取集合中元素个数
SREM key member1[member2…] 移除集合中一个/多个成员
127.0.0.1:6379> scard set
(integer) 5
127.0.0.1:6379> srem set 003
(integer) 1
127.0.0.1:6379> smembers set
1) "005"
2) "004"
3) "001"
4) "002"
SRANDMEMBER key [count] 随机返回集合中count个成员,count缺省值为1
SPOP key [count] 随机移除并返回集合中count个成员,count缺省值为1
127.0.0.1:6379> srandmember set
"004"
127.0.0.1:6379> srandmember set 2
1) "004"
2) "005"
127.0.0.1:6379> spop set
"004"
SMOVE source destination member 将source集合的成员member移动到destination集合
127.0.0.1:6379> smembers set
1) "006"
2) "003"
3) "005"
4) "004"
5) "001"
6) "002"
127.0.0.1:6379> smove set set2 003
(integer) 1
127.0.0.1:6379> smembers set2
1) "003"
127.0.0.1:6379> smembers set
1) "006"
2) "005"
3) "004"
4) "001"
5) "002"
SDIFF key1[key2…] 返回所有集合的差集 key1- key2 - …
SINTER key1 [key2…] 返回所有集合的交集
SUNION key1 [key2…] 返回所有集合的并集
-可以用来做–共同关注–相互关注–之类的
127.0.0.1:6379> sadd set1 a b c e f
(integer) 5
127.0.0.1:6379> sadd set2 a b e f g
(integer) 5
127.0.0.1:6379> sdiff set1 set2
1) "c"
127.0.0.1:6379> sinter set1 set2
1) "a"
2) "f"
3) "b"
4) "e"
127.0.0.1:6379> sunion set1 set2
1) "c"
2) "a"
3) "f"
4) "b"
5) "g"
6) "e"
SDIFFSTORE destination key1[key2…] 在SDIFF的基础上,将结果保存到集合中==(覆盖)==。不能保存到其他类型key
SINTERSTORE destination key1[key2…] 在SINTER的基础上,存储结果到集合中。覆盖
SUNIONSTORE destination key1 [key2…] 在SUNION的基础上,存储结果到及和张。覆盖
SSCAN KEY [MATCH pattern] [COUNT count] 在大量数据环境下,使用此命令遍历集合中元素,每次遍历部分
4.Hash(哈希)
Map集合,key-map!时候这个值是一个map集合!本质和String类型没有太大区别,还是一个简单的key-vlaue !
Redis hash 是一个string类型的field和value的映射表,hash特别适合用于存储对象。
Set就是一种简化的Hash,只变动key,而value使用默认值填充。可以将一个Hash表作为一个对象进行存储,表中存放对象的信息。
命令介绍
HSET key field value 将哈希表 key 中的字段 field 的值设为 value 。重复设置同一个field会覆盖,返回0
HMSET key field1 value1 [field2 value2…] 同时将多个 field-value (域-值)对设置到哈希表 key 中。
HMGET key field1 [field2…] 获取所有给定字段的值
HGETALL key 获取在哈希表key 的所有字段和值
127.0.0.1:6379> hset hash fie str1
(integer) 1
127.0.0.1:6379> hget hash fie
"str1"
127.0.0.1:6379> hset hash fie str2
(integer) 0
127.0.0.1:6379> hget hash fie
"str2"
127.0.0.1:6379> hmset hash fie1 001 fie2 002
OK
127.0.0.1:6379> hmget hash fie1 fie2
1) "001"
2) "002"
127.0.0.1:6379> hgetall hash
1) "fie"
2) "str2"
3) "fie1"
4) "001"
5) "fie2"
6) "002"
HDEL key field1 [field2…] 删除哈希表key中一个/多个field字段
#删除hash指定key字段!对应的value值也就消失了!
HLEN key 获取哈希表中字段的数量
HEXISTS key field 查看哈希表 key 中,指定的字段是否存在。
HKEYS key 获取哈希表key中所有的字段
HVALS key 获取哈希表中所有值
HSETX key field value 只有在字段 field 不存在时,设置哈希表字段的值。
HGET key field value 获取存储在哈希表中指定字段的值
HINCRBY key field n 为哈希表 key 中的指定字段的整数值加上增量n,并返回增量后结果 一样只适用于整数型字段
HINCRBYFLOAT key field n 为哈希表 key 中的指定字段的浮点数值加上增量 n。
HSCAN key cursor [MATCH pattern] [COUNT count] 迭代哈希表中的键值对。
--------------------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) "gyc"
2) "20"
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) 21
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"
Hash应用
Hash变更的数据user name age,尤其是用户信息之类的,经常变动的信息!Hash更适合于对象的存储,Sring更加适合字符串存储!
5.Zset(有序集合)
在set的基础上,增加了一个值,set k1 v1 zset k1 score1 v1
不同的是每个元素都会关联一个double类型的分数(score)。redis正是通过分数来为集合中的成员进行从小到大的排序。
score相同:按字典顺序排序
有序集合的成员是唯一的,但分数(score)却可以重复。
命令介绍
ZADD key score member1 [score2 member2] 向有序集合添加一个或多个成员,或者更新已存在成员的分数
ZCARD key 获取有序集合的成员数
ZCOUNT key min max 计算在有序集合中指定区间score的成员数
ZINCRBY key n member 有序集合中对指定成员的分数加上增量 n
ZSCORE key member 返回有序集中,成员的分数值
ZRANK key member 返回有序集合中指定成员的索引
ZRANGE key start end 通过索引区间返回有序集合成指定区间内的成员
ZRANGEBYLEX key min max 通过字典区间返回有序集合的成员
ZRANGEBYSCORE key min max 通过分数返回有序集合指定区间内的成员==-inf 和 +inf分别表示最小最大值,只支持开区间()==
ZLEXCOUNT key min max 在有序集合中计算指定字典区间内成员数量
ZREM key member1 [member2…] 移除有序集合中一个/多个成员
ZREMRANGEBYLEX key min max 移除有序集合中给定的字典区间的所有成员
ZREMRANGEBYRANK key start stop 移除有序集合中给定的排名区间的所有成员
ZREMRANGEBYSCORE key min max 移除有序集合中给定的分数区间的所有成员
ZREVRANGE key start end 返回有序集中指定区间内的成员,通过索引,分数从高到底
ZREVRANGEBYSCORRE key max min 返回有序集中指定分数区间内的成员,分数从高到低排序
ZREVRANGEBYLEX key max min 返回有序集中指定字典区间内的成员,按字典顺序倒序
ZREVRANK key member 返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序
ZINTERSTORE destination numkeys key1 [key2 …] 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中,numkeys:表示参与运算的集合数,将score相加作为结果的score
ZUNIONSTORE destination numkeys key1 [key2…] 计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中
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..
(integer) 2
127.0.0.1:6379> ZCARD myzset # 获取有序集合的成员数
(integer) 2
127.0.0.1:6379> ZCOUNT myzset 0 1 # 获取score在 [0,1]区间的成员数量
(integer) 1
127.0.0.1:6379> ZCOUNT myzset 0 2
(integer) 2
----------------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 m2
"7"
--------------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"
) "m3"
3) "m2"
#testset=>{abc,add,amaze,apple,back,java,redis} score均为0
------------------ZRANGEBYLEX---------------------------------
# 区间用法
127.0.0.1:6379> zadd testset 0 abc 0 add 0 amaze 0 apple 0 back 0 java 0 redis
(integer) 7
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] 区间内的成员 就是展示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"
# 其实就是左开右开 但是-代表所有所以( [都是一样的
127.0.0.1:6379> ZRANGEBYLEX testset (- (apple
1) "abc"
2) "add"
3) "amaze"
------------------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-----------
# 先倒排序 再筛选
# ZREVRANGE 就是zset reverse range 反转根据索引展示
127.0.0.1:6379> zadd myset 1 m1 2 m2 3 m3 4 m4 7 m7 9 m9
127.0.0.1:6379> ZRANGE myset 0 -1
1) "m1"
2) "m2"
3) "m3"
4) "m4"
5) "m7"
6) "m9"
127.0.0.1:6379> ZREVRANGE myset 0 3 # 按score递减排序,然后按索引,返回结果的 0~3
1) "m9"
2) "m7"
3) "m4"
4) "m3"
127.0.0.1:6379> ZREVRANGE myset 2 4 # 返回排序结果的 索引的2~4
1) "m4"
2) "m3"
3) "m2"
# 按score递减顺序 返回集合中分数在[2,6]之间的成员
127.0.0.1:6379> ZREVRANGEBYSCORE myset 6 2
1) "m4"
2) "m3"
3) "m2"
127.0.0.1:6379> ZREVRANGEBYSCORE myset 2 6
(empty list or set) # 这样写是报错的 因为不存在
127.0.0.1:6379> ZREVRANGEBYLEX testset [java (add # 按字典倒序 返回集合中(add,java]字典区间的成员
1) "java"
2) "back"
3) "apple"
4) "amaze"
-----------------------------补充---------------------------
# 补充这个是自动排序的根据首字母 如果score最小就最前面 否则在后面
127.0.0.1:6379> ZRANGE testset 0 -1
1) "java"
2) "redis"
# 这边发现添加的两个都是score为0的根据首字母排序了
127.0.0.1:6379> ZADD testset 0 hehe 0 xixi
(integer) 2
127.0.0.1:6379> ZRANGE testset 0 -1
1) "hehe"
2) "java"
3) "redis"
4) "xixi"
# 然后设置了score为1的 aaa实在最后
127.0.0.1:6379> ZADD testset 1 aaa
(integer) 1
127.0.0.1:6379> ZRANGE testset 0 -1
1) "hehe"
2) "java"
3) "redis"
4) "xixi"
5) "aaa"
-------------------------ZREVRANK------------------------------
# ZREVRANK 就是先倒排 再根据值找索引 位置
127.0.0.1:6379> ZREVRANK myset m7 # 按score递减顺序,返回成员m7索引
(integer) 1
127.0.0.1:6379> ZREVRANK myset m2
(integer) 4
# mathscore=>{(xm,90),(xh,95),(xg,87)} 小明、小红、小刚的数学成绩
# enscore=>{(xm,70),(xh,93),(xg,90)} 小明、小红、小刚的英语成绩
-------------------ZINTERSTORE--ZUNIONSTORE---------------------------------
127.0.0.1:6379> ZRANGE mathscore 0 -1
1) "xg"
2) "xm"
3) "xh"
127.0.0.1:6379> ZRANGE enscore 0 -1
1) "xm"
2) "xg"
3) "xh"
127.0.0.1:6379> ZRANGE enscore 0 -1 withscores
1) "xm"
2) "70"
3) "xg"
4) "90"
5) "xh"
6) "93"
# 将mathscore enscore进行合并 结果存放到sumscore
127.0.0.1:6379> ZINTERSTORE sumscore 2 mathscore enscore
(integer) 3
# 合并后的score是之前集合中所有score的和
127.0.0.1:6379> ZRANGE sumscore 0 -1 withscores
1) "xm"
2) "160"
3) "xg"
4) "177"
5) "xh"
6) "188"
# 就是取 两个数据的最小的值展示 带score排序的
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测试
四、三种特殊数据类型
1.geospatial 地理位置
官网:http://www.redis.cn/commands/geoadd.html
朋友的定位,附近的人,打车距离计算。
两地之间的距离,方圆几里的人
可以查询一些测试数据
只有六个命令:
-
geoadd:添加地理位置的经度纬度
-
geopos : 获取指定的经度纬度
-
geodist:返回两个位置的绝对距离
-
georadius:以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素
-
georadiusbymember 这个命令和 GEORADIUS 命令一样, 都可以找出位于指定范围内的元素, 但是 GEORADIUSBYMEMBER 的中心点是由给定的位置元素决定的, 而不是像 GEORADIUS 那样, 使用输入的经度和纬度来决定中心点
-
geohash:该命令将返回11个字符的Geohash字符串,所以没有精度Geohash,损失相比,使用内部52位表示。返回的geohashes具有以下特性:
- 他们可以缩短从右边的字符。它将失去精度,但仍将指向同一地区。
- 它可以在 geohash.org 网站使用,网址 http://geohash.org/。查询例子:http://geohash.org/sqdtr74hyu0.
- 与类似的前缀字符串是附近,但相反的是不正确的,这是可能的,用不同的前缀字符串附近。
有效经纬度
- 有效的经度从-180度到180度。
- 有效的纬度从-85.05112878度到85.05112878度。
关于GEORADIUS的参数
- 通过georadius就可以完成 附近的人功能
- withcoord:带上坐标
- withdist:带上距离,单位与半径单位相同
- COUNT n : 只显示前n个(按距离递增排序)
geoadd
# 坐标就是存储到zset的所以zset的命令都是可以用的 上面也提到过 所以查看集合的数据 也可以用zset命令来查看
# getadd 添加地理位置
# 规则:两级无法直接添加,我们一般会下载城市数据,直接通过java程序一次性导入!
# 有效的经度从-180度到180度。
# 有效的纬度从-85.05112878度到85.05112878度。
# 当坐标位置超出上述指定范围时,该命令将会返回一个错误。
127.0.0.1:6379[13]> GEOADD china:city 116.41667 39.91667 beijing
(integer) 1
127.0.0.1:6379[13]> GEOADD china:city 121.43333 34.50000 shanghai
(integer) 1
127.0.0.1:6379[13]> GEOADD china:city 117.20000 39.13333 tianjing
(integer) 1
127.0.0.1:6379[13]> GEOADD china:city 118.78333 32.05000 jiangsu
127.0.0.1:6379[13]> ZRANGE china:city 0 -1
1) "jiangsu"
2) "shanghai"
3) "tianjing"
4) "beijing"
geopos
获得当前定位:一定是一个坐标值!
127.0.0.1:6379[13]> GEOPOS china:city jiangsu
1) 1) "118.78332942724227905"
2) "32.04999907785209956"
# 可写多个
127.0.0.1:6379[13]> GEOPOS china:city jiangsu shanghai
1) 1) "118.78332942724227905"
2) "32.04999907785209956"
2) 1) "121.4333304762840271"
2) "34.49999971716130887"
geodist
指定单位的参数 unit 必须是以下单位的其中一个:
- m 表示单位为米。
- km 表示单位为千米。
- mi 表示单位为英里。
- ft 表示单位为英尺。
# 查看江苏到背景的直线距离
127.0.0.1:6379[13]> GEODIST china:city jiangsu beijing km
"900.4314"
georadius
以给定的经纬度为中心, 找出某一半径内的元素
# 再加上几个城市
127.0.0.1:6379[13]> geoadd china:city 114.06667 22.61667 shenzheng
(integer) 1
127.0.0.1:6379[13]> geoadd china:city 120.20000 30.26667 hangzhou
(integer) 1
127.0.0.1:6379[13]> geoadd china:city 106.45000 29.56667 chongqin
(integer) 1
127.0.0.1:6379[13]> GEORADIUS china:city 110 30 1000 km
1) "chongqin"
2) "shenzheng"
3) "hangzhou"
4) "jiangsu"
127.0.0.1:6379[13]> GEORADIUS china:city 110 30 500 km
1) "chongqin"
# withdist 显示到中间距离的位置 withcoord 显示他人的定位信息(坐标)
127.0.0.1:6379[13]> GEORADIUS china:city 110 30 1000 km withcoord withdist
1) 1) "chongqin"
2) "346.0548"
3) 1) "106.4500012993812561"
2) "29.56666939001875249"
2) 1) "shenzheng"
2) "915.6424"
3) 1) "114.06667023897171021"
2) "22.61666928352524764"
3) 1) "hangzhou"
2) "981.3098"
3) 1) "120.20000249147415161"
2) "30.2666706589875858"
4) 1) "jiangsu"
2) "867.3741"
3) 1) "118.78332942724227905"
2) "32.04999907785209956"
# 带上count 1 就是在筛选之上 选择一个展示 2就是前两个...
127.0.0.1:6379[13]> GEORADIUS china:city 110 30 1000 km withcoord withdist count 1
1) 1) "chongqin"
2) "346.0548"
3) 1) "106.4500012993812561"
2) "29.56666939001875249"
GEORADIUSBYMEMBER
# 找出位于指定元素周围的其他元素!
127.0.0.1:6379[13]> GEORADIUSBYMEMBER china:city jiangsu 1000 km
1) "jiangsu"
2) "shanghai"
3) "tianjing"
4) "beijing"
5) "hangzhou"
127.0.0.1:6379[13]> GEORADIUSBYMEMBER china:city jiangsu 500 km
1) "jiangsu"
2) "shanghai"
3) "hangzhou"
1234567891011
GEOHASH 命令
返回一个或多个位置元素的 Geohash 表示
该命令将返回11个字符的Geohash字符串!
# 将二维的经纬度转换为一维的字符串,如果两个字符串越接近,那么则距离越近!
127.0.0.1:6379[13]> GEOHASH china:city jiangsu shanghai hangzhou
1) "wtsqqfx2u00"
2) "wwnk72911d0"
3) "wtmkpjyuph0"
12345
GEO 底层的实现原理其实就是 Zset!
我们可以使用Zset命令来操作geo!
前面已经提及多次。
127.0.0.1:6379[13]> ZRANGE china:city 0 -1
1) "chongqin"
2) "shenzheng"
3) "hangzhou"
4) "jiangsu"
5) "shanghai"
6) "tianjing"
7) "beijing"
127.0.0.1:6379[13]> ZRANGEBYLEX china:city - +
1) "chongqin"
2) "shenzheng"
3) "hangzhou"
4) "jiangsu"
5) "shanghai"
6) "tianjing"
7) "beijing"
127.0.0.1:6379[13]> ZREM china:city jiangsu
(integer) 1
127.0.0.1:6379[13]> ZRANGE china:city 0 -1
1) "chongqin"
2) "shenzheng"
3) "hangzhou"
4) "shanghai"
5) "tianjing"
6) "beijing"
2.Hyperloglog
Redis HyperLogLog 是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。
花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。
因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以 HyperLogLog 不能像集合那样,返回输入的各个元素。
其底层使用string数据类型
什么是基数?
数据集中不重复的元素的个数。
网页的 UV (一个人访问一个网站多次,但是还是算作一个人!)
传统实现,存储用户的id,然后每次进行比较。当用户变多之后这种方式及其浪费空间,而我们的目的只是计数,Hyperloglog就能帮助我们利用最小的空间完成。
命令 | 描述 |
---|---|
PFADD key element1 [elememt2…] | 添加指定元素到 HyperLogLog 中 |
PFCOUNT key [key] | 返回给定 HyperLogLog 的基数估算值。 |
PFMERGE destkey sourcekey [sourcekey…] | 将多个 HyperLogLog 合并为一个 HyperLogLog |
----------PFADD--PFCOUNT---------------------
# 添加元素
127.0.0.1:6379[13]> PFADD myelemx a b c d e f g h i j k
(integer) 1
# hyperloglog底层使用String
127.0.0.1:6379[13]> type myelemx
string
# 估算myelemx的基数
127.0.0.1:6379[13]> PFCOUNT myelemx a # 不存在的key也不会报错
(integer) 11
127.0.0.1:6379[13]> PFCOUNT myelemx
(integer) 11
127.0.0.1:6379[13]> pfadd myelems a c d j k m n o p q
(integer) 1
# 估算两个元素中的基数个数 相同的不纳入计算
127.0.0.1:6379[13]> PFCOUNT myelemx myelems
(integer) 16
127.0.0.1:6379[13]> PFCOUNT myelems
(integer) 10
# 其实就是字符串
127.0.0.1:6379[13]> get myelemx
"HYLL\x01\x00\x00\x00\x0b\x00\x00\x00\x00\x00\x00\x80DE\x8cB&\x80@\x89\x88H_\x84@\xfc\x80EV\x94F\xca\x80D<\x848\x80B=\x80K\x83\x80B\xed\x84A\xfc\x8cC\x93\x84C\xf9\x80Bm\x80BZ"
----------------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.BitMap(位图)
位存储
统计疫情感染人数:0 1 0 1,统计用户信息,活跃,不活跃,打开,365打卡,两个状态的,都可以使用bitmaps来存储
bitmap 位图,也是一种数据结构!都是操作二进制位来进行记录,都只有 0 1两种状态
365天 = 365 bit, 1字节 = 8bit, 46个字节左右!
使用位存储,信息状态只有 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
127.0.0.1:6379[13]> get sign
"\xb4"