目录
ZRANGEBYSCORE 查出成绩 80 分以下的所有同学
简介
概述
Redis(Remote Dictionary Server)是一种开源的、高性能的键值(Key-Value)存储系统,它提供了多种数据结构的存储,如 :String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)。
特点
- Redis 是使用 C语言 编写的一种基于内存的数据库,对数据的读写操作都是在内存中完成,因此读写速度非常快,常用于缓存,消息队列、分布式锁等场景。
- Redis 提供了多种数据类型来支持不同的业务场景,比如 String(字符串)、Hash(哈希)、 List (列表)、Set(集合)、Zset(有序集合)、Bitmaps(位图)、HyperLogLog(基数统计)、GEO(地理信息)、Stream(流),并且对数据类型的操作都是原子性的,因为执行命令由单线程负责的,不存在并发竞争的问题。
- Redis 还支持事务 、持久化、Lua 脚本、多种集群方案(主从复制模式、哨兵模式、切片机群模式)、发布/订阅模式,内存淘汰机制、过期删除机制等等。
数据结构
常用命令
Redis为了方便我们学习,将操作不同数据类型的命令也做了分组,在官网( 点击此处进入redis官网 )可以查看到不同的命令:
通用命令
通用指令是部分数据类型的,都可以使用的指令,常见的有:
- KEYS:查看符合模板的所有key
- DEL:删除一个指定的key
- EXISTS:判断key是否存在
- EXPIRE:给一个key设置有效期,有效期到期时该key会被自动删除
- TTL:查看一个KEY的剩余有效期
通过help [command] 可以查看一个命令的具体用法,例如:
keys
0.0.0.0:6379> set email 13213@qq.com
OK
0.0.0.0:6379> keys *
1) "email"
2) "age"
3) "name"
0.0.0.0:6379> keys a*
1) "age"
贴心小提示:在生产环境下,不推荐使用keys 命令,因为这个命令在key过多的情况下,效率不高
del
luyuan@ubuntu:~$ redis-cli -h 0.0.0.0 -p 6379 -a 123456
0.0.0.0:6379> help del
DEL key [key ...]
summary: Delete a key
since: 1.0.0
group: generic
0.0.0.0:6379> del name #删除单个
(integer) 1
0.0.0.0:6379> keys * #查看当前所有keys
1) "email"
2) "age"
# 设置几个key 和 value
0.0.0.0:6379> mset k1 v1 k2 v2 k3 v3
OK
0.0.0.0:6379> keys *
1) "age"
2) "email"
3) "k1"
4) "k2"
5) "k3"
# 删除几个key 多删除一个k4 但是它不存在
0.0.0.0:6379> del k1 k2 k3 k4
(integer) 3 # 成功删除了3个key
0.0.0.0:6379> keys *
1) "age"
2) "email"
exists
0.0.0.0:6379> help exists
EXISTS key [key ...]
summary: Determine if a key exists
since: 1.0.0
group: generic
0.0.0.0:6379> exists age # 查看age是否存在
(integer) 1 # age存在
0.0.0.0:6379> exists gender
(integer) 0 #
expire 与 ttl
内存非常宝贵,对于一些数据,我们应当给他一些过期时间,当过期时间到了之后,他就会自动被删除~
0.0.0.0:6379> expire time 20 # 设置 time 过期时间为20s
(integer) 1
0.0.0.0:6379> ttl time
(integer) 17
0.0.0.0:6379> ttl time
(integer) 14
0.0.0.0:6379> ttl time
(integer) 13
0.0.0.0:6379> ttl time
(integer) 8
0.0.0.0:6379> ttl time
(integer) -2
# 查看当前key
0.0.0.0:6379> keys *
1) "age"
2) "email"
0.0.0.0:6379> ttl age
(integer) -1
0.0.0.0:6379> ttl email
(integer) -1
注:
ttl 查看当前key还有多久过期
- 返回-2 代表 key 过期了
- 返回-1 代表 key 没有过期时间
String 命令
String类型,也就是字符串类型,是Redis中最简单的存储类型。
其value是字符串,不过根据字符串的格式不同,又可以分为3类:
- string:普通字符串
- int:整数类型,可以做自增.自减操作
- float:浮点类型,可以做自增.自减操作
key
value
msg
hello world
id
1
price
88.20
String的常见命令有:
- SET:添加或者修改已经存在的一个String类型的键值对
- GET:根据key获取 String类型的value
- MSET:批量添加多个 String类型的键值对
- MGET:根据多个 key 获取多个 String类型的value
- INCR:让一个整型的 key 自增1
- INCRBY:让一个整型的 key 自增并指定步长,
- 例如:incrby num 2 让num值自增2
- INCRBYFLOAT:让一个浮点类型的数字自增并指定步长
- SETNX:添加一个 String类型的键值对,前提是这个 key 不存在,否则不执行
- SETEX:添加一个 String类型的键值对,并且指定有效期
贴心小提示:
以上命令除了INCRBYFLOAT 都是常用命令
SET 和GET:
如果key不存在则是新增,如果存在则是修改
luyuan@ubuntu:~$ redis-cli -h 0.0.0.0 -p 6379 -a 123456
0.0.0.0:6379> set name luyuan // 原本不存在
OK
0.0.0.0:6379> get name
"luyuan"
0.0.0.0:6379> set name jack
OK
0.0.0.0:6379> get name
"jack"
MSET和MGET
0.0.0.0:6379> MSET k1 v1 k2 v2 k3 v3
OK
0.0.0.0:6379> MGET name age k1 k2 k3
1) "jack"
2) "18"
3) "v1"
4) "v2"
5) "v3"
INCR和INCRBY和DECY
0.0.0.0:6379> get age
"18"
0.0.0.0:6379> incr age # 自增1
(integer) 19
0.0.0.0:6379> get age
"19"
0.0.0.0:6379> incrby age 2 # 自增2
(integer) 21
0.0.0.0:6379> incrby age -2 # 自减2
(integer) 19
0.0.0.0:6379> decr age # 自减2
(integer) 18
0.0.0.0:6379> get age
"18"
0.0.0.0:6379>
SETNX
0.0.0.0:6379> help setnx
SETNX key value
summary: Set the value of a key, only if the key does not exist
since: 1.0.0
group: string
0.0.0.0:6379> set name Jack
OK
0.0.0.0:6379> setnx name lisi
(integer) 0 # name已经存在 添加key失败
0.0.0.0:6379> get name
"Jack"
0.0.0.0:6379> setnx name2 lisi
(integer) 1 #name2不存在 添加key成功
0.0.0.0:6379> get name2
"lisi"
0.0.0.0:6379>
SETEX
0.0.0.0:6379> help setex
SETEX key seconds value
summary: Set the value and expiration of a key
since: 2.0.0
group: string
0.0.0.0:6379> setex time 20 20s
OK
0.0.0.0:6379> ttl time
(integer) 16
0.0.0.0:6379> ttl time
(integer) 6
0.0.0.0:6379> ttl time
(integer) -2
or
0.0.0.0:6379> set time 20s EX 20
OK
0.0.0.0:6379> ttl time
(integer) 18
0.0.0.0:6379> ttl time
(integer) 1
0.0.0.0:6379> ttl time
(integer) -2
0.0.0.0:6379>
注:
setex time 20 20s = set time 20s EX 20
Redis 命令 Key 的层级结构
Redis没有类似 MySQL 中的 Table 的概念,我们该如何区分不同类型的key呢?
例如:
需要存储用户,商品信息到redis,
- 有一个用户id是1,
- 有一个商品id恰好也是1
此时如果使用id作为key,那就会冲突了,该怎么办?
我们可以通过给key添加前缀加以区分,不过这个前缀不是随便加的,有一定的规范:
Redis的key允许有多个单词形成层级结构,多个单词之间用':'隔开,格式如下:
这个格式并非固定,也可以根据自己的需求来删除或添加词条。
例如我们的项目名称叫 project,有user和product两种不同类型的数据,我们可以这样定义key:
KEY
VALUE
project:user:1
{"id":1, "name": "Jack", "age": 21}
project:product:1
{"id":1, "name": "小米11", "price": 4999}
0.0.0.0:6379> set project:user:1 '{"id":1, "name": "Jack", "age": 21}'
OK
0.0.0.0:6379> set project:product:1 '{"id":1, "name": "小米11", "price": 4999} '
key层级关系 :
- project product
- project user
Hash命令
Hash类型,也叫散列,其value是一个无序字典,类似于Java中的HashMap结构。
String结构是将对象序列化为JSON字符串后存储,当需要修改对象某个字段时很不方便:
Hash结构可以将对象中的每个字段独立存储,可以针对单个字段做CRUD:
Hash类型的常见命令
- HSET key field value:添加或者修改hash类型key的field的值
- HGET key field:获取一个hash类型key的field的值
- HMSET:批量添加多个hash类型key的field的值
- HMGET:批量获取多个hash类型key的field的值
- HGETALL:获取一个hash类型的key中的所有的field和value
- HKEYS:获取一个hash类型的key中的所有的field
- HINCRBY:让一个hash类型key的字段值自增并指定步长
- HSETNX:添加一个hash类型的key的field值,前提是这个field不存在,否则不执行
贴心小提示:哈希结构也是我们以后实际开发中常用的命令哟
HSET和HGET
0.0.0.0:6379> HSET luyuan:user:1 name luyuan
(integer) 1
0.0.0.0:6379> HSET luyuan:user:1 age 18
(integer) 1
0.0.0.0:6379> HGET luyuan:user:1 name
"luyuan"
0.0.0.0:6379> HGET luyuan:user:1 age
"18"
HMSET和HMGET
0.0.0.0:6379> HMSET luyuan:user:2 name yasuo
OK
0.0.0.0:6379> HMSET luyuan:user:2 name yatuo age 22 gender man
OK
0.0.0.0:6379> HMGET luyuan:user:2 name age gender
1) "yatuo"
2) "22"
3) "man"
HGETALL
0.0.0.0:6379> HGETALL luyuan:user:2
1) "name"
2) "yatuo"
3) "age"
4) "22"
5) "gender"
6) "man"
HKEYS和HVALS
0.0.0.0:6379> HKEYS luyuan:user:2
1) "name"
2) "age"
3) "gender"
0.0.0.0:6379> HVALS luyuan:user:2
1) "yatuo"
2) "22"
3) "man"
HINCRBY
0.0.0.0:6379> HINCRBY luyuan:user:2 age 2
(integer) 24
0.0.0.0:6379> HINCRBY luyuan:user:2 age 2
(integer) 26
0.0.0.0:6379> HVALS luyuan:user:2
1) "yatuo"
2) "26"
3) "man"
0.0.0.0:6379> HINCRBY luyuan:user:2 age -2
(integer) 24
0.0.0.0:6379> HINCRBY luyuan:user:2 age -2
(integer) 22
0.0.0.0:6379> HVALS luyuan:user:2
1) "yatuo"
2) "22"
3) "man"
HSETNX
0.0.0.0:6379> HSETNX luyuan:user:2 phone 18877776666
(integer) 1
0.0.0.0:6379> HGETALL luyuan:user:2
1) "name"
2) "yatuo"
3) "age"
4) "22"
5) "gender"
6) "man"
7) "phone"
8) "18877776666"
List 命令
Redis中的 List 类型与 Java 中的 LinkedList 类似,可以看做是一个双向链表结构。既可以支持正向检索和也可以支持反向检索。
特征也与LinkedList类似:
- 有序
- 元素可以重复
- 插入和删除快
- 查询速度一般
常用来存储一个有序数据,例如:朋友圈点赞列表,评论列表等。
List的常见命令有:
- LPUSH key element ... :向列表左侧插入一个或多个元素
- LPOP key:移除并返回列表左侧的第一个元素,没有则返回nil
- RPUSH key element ... :向列表右侧插入一个或多个元素
- RPOP key:移除并返回列表右侧的第一个元素
- LRANGE key star end:返回一段角标范围内的所有元素
- BLPOP和BRPOP:与 LPOP 和 RPOP 类似,只不过在没有元素时等待指定时间,而不是直接返回nil
LPUSH和RPUSH
127.0.0.1:6379> LPUSH luyuan:users:1 1 2 3
(integer) 3
127.0.0.1:6379> RPUSH luyuan:users:1 4 5 6
(integer) 6
LPOP 和 RPOP
127.0.0.1:6379> LPOP luyuan:users:1
"3"
127.0.0.1:6379> RPOP luyuan:users:1
"6"
LRANGE
127.0.0.1:6379> LRANGE luyuan:users:1 1 2
1) "1"
2) "4"
BLPOP 和 BRPOP
127.0.0.1:6379> BLPOP users2 1000
输入后会阻塞 1000 s 直到users2有值
两外一个端LPUSH一个users2 阻塞结束 获取到 users2
127.0.0.1:6379> BLPOP users2 1000
1) "users2"
2) "jack"
(19.18s)
SET 命令
Redis的 Set 结构与 Java 中的 HashSet 类似,可以看做是一个 value 为 null 的 HashMap 。因为也是一个 hash 表,因此具备与 HashSet 类似的特征:
- 无序
- 元素不可重复
- 查找快
- 支持交集.并集.差集等功能
Set类型的常见命令
- SADD key member ... :向set中添加一个或多个元素
- SREM key member ... : 移除set中的指定元素
- SCARD key: 返回set中元素的个数
- SISMEMBER key member:判断一个元素是否存在于set中
- SMEMBERS:获取set中的所有元素
- SINTER key1 key2 ... :求key1与key2的交集
- SDIFF key1 key2 ... :求key1与key2的差集
- SUNION key1 key2 ..:求key1和key2的并集
案例
- 将下列数据用Redis的Set集合来存储:
- 张三的好友有:李四.王五.赵六
- 李四的好友有:王五.麻子.二狗
- 利用Set的命令实现下列功能:
- 计算张三的好友有几人
- 计算张三和李四有哪些共同好友
- 查询哪些人是张三的好友却不是李四的好友
- 查询张三和李四的好友总共有哪些人
- 判断李四是否是张三的好友
- 判断张三是否是李四的好友
- 将李四从张三的好友列表中移除
# 张三的好友有:李四.王五.赵六
# 李四的好友有:王五.麻子.二狗
127.0.0.1:6379> SADD zs lisi wangwu zhaoliu
(integer) 3
127.0.0.1:6379> SADD ls wangwu mazi ergou
(integer) 3
# 计算张三的好友有几人
127.0.0.1:6379> SCARD zs
(integer) 3
# 计算张三和李四有哪些共同好友
127.0.0.1:6379> SINTER zs ls
1) "wangwu"
# 查询哪些人是张三的好友却不是李四的好友
127.0.0.1:6379> SDIFF zs ls
1) "zhaoliu"
2) "lisi"
# 查询张三和李四的好友总共有哪些人
127.0.0.1:6379> SUNION zs ls
1) "wangwu"
2) "mazi"
3) "zhaoliu"
4) "lisi"
5) "ergou"
# 判断李四是否是张三的好友
127.0.0.1:6379> SISMEMBER ls zhangsan
(integer) 0
# 判断张三是否是李四的好友
127.0.0.1:6379> SISMEMBER zs lisi
(integer) 1
# 将李四从张三的好友列表中移除
127.0.0.1:6379> SREM zs lisi
(integer) 1
# 查看张三的好友列表
127.0.0.1:6379> SMEMBERS zs
1) "wangwu"
2) "zhaoliu"
127.0.0.1:6379>
SortedSet 命令(☆☆☆☆☆)
Redis 的 SortedSet 是一个可排序的 set 集合,与 Java 中的 TreeSet 有些类似,但底层数据结构却差别很大。SortedSet 中的每一个元素都带有一个 score 属性,可以基于 score 属性对元素排序,底层的实现是一个跳表(SkipList)加 hash 表。
SortedSet 具备下列特性:
- 可排序
- 元素不重复
- 查询速度快
因为 SortedSet 的可排序特性,经常被用来实现排行榜这样的功能。
SortedSet 的常见命令有:
- ZADD key score member:添加一个或多个元素到 sorted set ,如果已经存在则更新其 score 值
- ZREM key member:删除 sorted set 中的一个指定元素
- ZSCORE key member : 获取 sorted set 中的指定元素的 score 值
- ZRANK key member:获取 sorted set 中的指定元素的排名
- ZCARD key:获取 sorted set 中的元素个数
- ZCOUNT key min max:统计 score 值在给定范围内的所有元素的个数
- ZINCRBY key increment member:让 sorted set 中的指定元素自增,步长为指定的increment值
- ZRANGE key min max:按照 score 排序后,获取指定排名范围内的元素
- ZRANGEBYSCORE key min max:按照 score 排序后,获取指定score范围内的元素
- ZDIFF.ZINTER.ZUNION:求 差集,交集,并集
注意:所有的排名默认都是升序,如果要降序则在命令的 Z 后面添加 REV 即可,
例如:
- 升序获取 sorted set 中的指定元素的排名:ZRANK key member
- 降序获取 sorted set 中的指定元素的排名:ZREVRANK key memeber
案例
ZADD 添加学生信息
127.0.0.1:6379> ZADD sort 85 Jack 89 Lucy 82 Rose 95 Tom 78 Jerry 92 Amy 76 Miles
(integer) 7
ZREM 删除Tom
127.0.0.1:6379> ZREM sort Tom
(integer) 1
ZSCORE 获取Amy的分数
127.0.0.1:6379> ZSCORE sort Amy
"92"
ZRANK 和 ZREVRANK 获取Rose同学的排名
下标是从0开始 0表示第一
127.0.0.1:6379> ZRANK sort Rose
(integer) 2 # 默认排序 第三
127.0.0.1:6379> ZREVRANK sort Rose
(integer) 3 # 降序排序 第四
ZCOUNT 查询 80 分以下有几个学生
127.0.0.1:6379> ZCOUNT sort 0 80
(integer) 2
ZINCRBY 给 Amy 加 2 分
127.0.0.1:6379> ZINCRBY sort 2 Amy
"94"
ZREVRANGE 查出成绩前3名的同学
排序遵循上图
127.0.0.1:6379> ZREVRANGE sort 0 2
1) "Amy"
2) "Lucy"
3) "Jack"
ZRANGEBYSCORE 查出成绩 80 分以下的所有同学
127.0.0.1:6379> ZRANGEBYSCORE sort 0 80
1) "Miles"
2) "Jerry"
总结 ---- 精华部分
关于Redis
Redis是一个基于内存的非关系型NoSQL数据库,用来解决高并发的问题.
1.1 特点
开源的,使用C编写,基于内存且支持持久化
高性能的Key-Value的NoSQL数据库
支持数据类型丰富,字符串string,列表list,散列hash,集合set,有序集合sorted set
支持多种编程语言(C C++ Python Java PHP ... )
1.2 应用场景
排行榜;
短信验证码;
缓存网站中大量被访问的页面;
共同关注,共同好友;
增量爬虫,分布式爬虫;
消息队列.
1.3 服务命令
服务端操作
systemctl status redis
systemctl start redis
systemctl stop redis
systemctl restart redis
客户端连接
redis-cli -h 主机地址 -p 6379 -a 密码
1.4 配置文件
1.4.1 配置文件位置
gedit /etc/redis.conf
1.4.2 常见配置
切记:修改完配置文件后一定要重启Redis服务!
设置密码
requirepass 123456
设置远程连接
bind 127.0.0.1 ::1 //将此行注释 protected-mode no //将保护模式的yes改为no
2.Redis命令
2.1 全局命令
查看所有的key: KEYS *
切换库: SELECT number
删除KEY: DEL key
2.2 字符串命令
应用场景:缓存热门数据、短信验证码、常规计数比如点赞数、评论数等
增: SET key value NX EX 秒数
查: GET key
整型+1操作: INCR key
整型-1操作: DECR key
2.3 列表命令
应用场景:消息队列
头部压入元素: LPUSH key value
尾部压入元素: RPUSH key value
尾部阻塞弹出元素: BRPOP key timeout
timeout 为 0时,表示永久阻塞,直接有元素压入
查看列表元素: LRANGE key start stop
查看长度: LLEN key
2.4 哈希散列类型
应用场景:存储对象类型的数据,存储购物车数据等
设置单个key-field-value: HSET key field value
设置多个key-field-value: HMSET key field value field value field value ...
获取所有key-field-value: HGETALL key
2.5 集合
应用场景:共同关注、共同好友、增量爬虫、分布式爬虫
集合中添加成员:SADD key member member ... ...
查看集合中成员:SMEMBERS key
查看集合交集: SINTERSTORE destination key1 key2
2.6 有序集合
应用场景:各种排行榜
添加成员:zadd key score member
查看成员[升序]: zrange key start stop [withscores]
查看成员[降序]: zrevrange key start stop [withscores]
小常识
在Linux系统中,IP地址
0.0.0.0
通常被用来表示所有可用的网络接口。当一个服务绑定到0.0.0.0
上的某个端口时,这意味着该服务将会在所有的网络接口上监听,包括但不限于以太网卡、无线网卡以及回环接口(lo)。对于本机上的进程来说,
0.0.0.0
可以被视为一种通配符,允许任何网络接口接收数据。因此,当你在Linux上运行一个服务并将其绑定到0.0.0.0
,这表示该服务对所有连接到这台机器的网络设备都是可访问的。然而,如果你想仅限于本机访问,通常会使用回环地址
127.0.0.1
。这个地址专门用于本地主机,数据不会离开本机,而是直接在操作系统内部循环。总结一下:
0.0.0.0
在Linux中代表所有网络接口,即对外部网络也是开放的。127.0.0.1
专指本机的回环接口,只能在本机上访问。