非关系型数据库 -- redis
基本特性:
- redis一共有16个库
- redis使用键值对完成数据存储
- 每一个库当中可以保存固定数量的键值对
- redis 的默认端口是6379
- redis支持的值的类型非常丰富,支持目前最为流行的json 也支持自定义数据类型
- redis数据的读写都直接的发生在内存中
- redis支持AOF 和 RDB 两种方式持久化,将内存中的数据写入指定文件以实现持久化
- redis 支持哨兵模式,对于redis 进程进行监控,一旦出现问题可以尝试恢复redis服务进程
- redis自带集群模式,自动形成redis集群,自动划分每一个库维护的键值对数量
- 丰富的开发语言支持
|---------|-----------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
| 差别点 | mysql | redis |
| 数据存储 | 1. mysql 关系型数据库在写入数据时,一般以直接将数据写入磁盘 2. 关系型数据库一般以数据表(二维表)形式存储, 3. 存储值的类型区别较大,mysql 主要处理的值的类型可以分为字符型、数值型、时间日期、二进制型 | 1、 数据优先写入到内存中,再通过某些方式同步到数据文件中 2、redis 可以通过两种方式将内存中数据写入系统文件 3、 redis 在进行数据存储以键值对形式存储数据,不论哪种类型的数据,redis都是通过键来完成数据处理 4、 redis 支持字符串、列表、集合等,对于编程支持较好的语言。 |
| 数据存储限制 | mysql 数据以数据表的格式进行存储,数据存储几乎没有上限 | redis 数据一共有16个库,每一个库独立进行数据存储,每一个库以一个数据槽对应一组键值对的方式进行数据存储,而对于单个redis实例或者整个redis集群,数据槽(slot)的数量是固定。 |
| 扩展功能 | 关系型数据库集群的水平扩展或者集群管理,一般需要结合额外的数据库管理服务实现。比如:mha、 | redis 自带集群管理和监控功能,可以实现自动failover 故障转移 |
| 数据备份和恢复 | 可以按照备份的方式分为: 冷备份 热备份 逻辑备份 物理备份 全量备份 增量备份等 | 对于redis 而言,数据的备份就是以数据持久化来实现。 |
适用场景:
- 数据缓存
- 数据复制
- sessions 管理
- 快速数据处理
使用行业:
金融服务
游戏
医保
零售
一、安装
[root@bogon ~]# dnf module list redis
Last metadata expiration check: 2:42:31 ago on Fri 30 Aug 2024 12:35:20 PM CST.
CentOS Stream 9 - AppStream
Name Stream Profiles Summary
redis 7 common [d] Redis persistent key-value database
Hint: [d]efault, [e]nabled, [x]disabled, [i]nstalled
[root@bogon ~]# dnf -y install redis
Last metadata expiration check: 2:43:18 ago on Fri 30 Aug 2024 12:35:20 PM CST.
Dependencies resolved.
==============================================================================================================================================================
Package Architecture Version Repository Size
==============================================================================================================================================================
Installing:
redis x86_64 6.2.7-1.el9 appstream 1.3 M
Transaction Summary
==============================================================================================================================================================
Install 1 Package
Total download size: 1.3 M
Installed size: 4.7 M
Downloading Packages:
redis-6.2.7-1.el9.x86_64.rpm 2.1 MB/s | 1.3 MB 00:00
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Total 822 kB/s | 1.3 MB 00:01
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Running scriptlet: redis-6.2.7-1.el9.x86_64 1/1
Installing : redis-6.2.7-1.el9.x86_64 1/1
Running scriptlet: redis-6.2.7-1.el9.x86_64 1/1
Verifying : redis-6.2.7-1.el9.x86_64 1/1
Installed:
redis-6.2.7-1.el9.x86_64
Complete!
[root@bogon ~]# systemctl enable --now redis
redis-sentinel.service redis.service
[root@bogon ~]# systemctl enable --now redis.service
Created symlink /etc/systemd/system/multi-user.target.wants/redis.service → /usr/lib/systemd/system/redis.service.
[root@bogon ~]# ss -anput | grep redis
tcp LISTEN 0 511 127.0.0.1:6379 0.0.0.0:* users:(("redis-server",pid=3551,fd=6))
tcp LISTEN 0 511 [::1]:6379 [::]:* users:(("redis-server",pid=3551,fd=7))
[root@bogon ~]# redis-cli ping
PONG
redis 一般可以作为a、 关系型数据的缓存加速服务部署 b、 作为应用数据库
而redis所有的数据以键值对的形式存储,下面简单了解redis数据操作语句。
redis-cli指令一般默认连接 127.0.0.1 的 6379 端口, 通过 -h 和 -p 选项可以连接其他ip和端口的redis服务端
二、指令
1.ping 不属于数据操作语句 验证数据库是否运行
root@bogon ~]# ss -anput | grep redis
tcp LISTEN 0 511 127.0.0.1:6379 0.0.0.0:* users:(("redis-server",pid=3551,fd=6))
tcp LISTEN 0 511 [::1]:6379 [::]:* users:(("redis-server",pid=3551,fd=7))
[root@bogon ~]# redis-cli ping
PONG
[root@bogon ~]# systemctl stop redis
[root@bogon ~]# redis-cli ping
Could not connect to Redis at 127.0.0.1:6379: Connection refused
2.keys 列出键
[root@bogon ~]# systemctl start redis
[root@bogon ~]# redis-cli
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> keys *
(empty array)
3.del 删除键
基于不同数据类型,对应的语句
redis社区版支持一下数据类型,企业版数据支持更加丰富
String - 字符串
Hash - 哈希值
List - 列表
Set - 集合
Sorted set - 有序集合
Stream - 数据流 一个特殊形式的字符串,只能在字符串的末尾新增,类似于日志文件
Bitmap - 位映射 一种比较特殊的字符串 ,可以对字符串进行位运算
Bitfield - 可以从bit位进行字符串数据的批量操作
Geospatial - 地理 基于经纬度实现定位
字符串, 最大不超过512m
4.set key value 键值对的生存时间
127.0.0.1:6379> set bike diamon
OK
127.0.0.1:6379> keys *
1) "bike"
127.0.0.1:6379> set bike1 value1 ex 10 // 设定键的生存时间
OK
127.0.0.1:6379> keys *
1) "bike"
2) "bike1"
127.0.0.1:6379> get bike1
"value1"
127.0.0.1:6379> keys *
1) "bike"
127.0.0.1:6379> set bike1 value1 nx // 如果键不存在,则创建新的键值对,
// 如果存在的话,不做任何事退出
OK
127.0.0.1:6379> get bike1
"value1"
127.0.0.1:6379> set bike1 value1 nx
(nil)
127.0.0.1:6379> set bike1 value2 nx
(nil)
127.0.0.1:6379> get bike1
"value1"
127.0.0.1:6379> set bike2 value2 nx
OK
127.0.0.1:6379> set bike1 value3 xx // 如果键存在,则更新值
// 如果键不存在,不会创建新的键
OK
127.0.0.1:6379> get bike1
"value3"
127.0.0.1:6379> keys *
1) "bike"
2) "bike2"
3) "bike1"
127.0.0.1:6379> set bike3 aab xx
(nil)
127.0.0.1:6379> keys *
1) "bike"
2) "bike2"
3) "bike1"
5.mset 一次性设置多个键值对 为键值对可以调整的参数与单个键值对创建的参数一致
127.0.0.1:6379> mset bike:1 "Deimos" bike:2 "Ares" bike:3 "Vanth"
OK
127.0.0.1:6379> keys *
1) "bike"
2) "bike1"
3) "bike2"
4) "bike:1"
5) "bike:3"
6) "bike:2"
6.INCR INCRBY 自增,注意此时字符串的字符一般为数字字符
127.0.0.1:6379> set counter 0
OK
127.0.0.1:6379> get counter
"0"
127.0.0.1:6379> incr counter
(integer) 1
127.0.0.1:6379> get counter
"1"
127.0.0.1:6379> incrby counter 5
(integer) 6
127.0.0.1:6379> get counter
"6"
三、列表处理
redis每一个列表最多保存 2^32 - 1 (4,294,967,295)
添加元素:lpush rpush
移除元素: rpop lpop
获取列表长度: llen
移动列表元素到新列表: lmove
获取列表元素:lrange
控制列表元素数量:ltrim
127.0.0.1:6379> LPUSH queue1 user1
(integer) 1
127.0.0.1:6379> LPUSH queue1 user2
(integer) 2
127.0.0.1:6379> LPUSH queue1 user3
(integer) 3
127.0.0.1:6379> RPOP queue1
"user1"
127.0.0.1:6379> RPOP queue1
"user2"
127.0.0.1:6379> RPOP queue1
"user3"
127.0.0.1:6379> keys queue1
(empty array)
127.0.0.1:6379> keys *
1) "bike:1"
2) "bike1"
3) "bike2"
4) "bike:2"
5) "bike:3"
6) "counter"
7) "bike"
127.0.0.1:6379> RPUSH queue2 user1
(integer) 1
127.0.0.1:6379> RPUSH queue2 user2
(integer) 2
127.0.0.1:6379> RPUSH queue2 user3
(integer) 3
127.0.0.1:6379> rpop queue2
"user3"
127.0.0.1:6379> RPUSH queue2 user3
(integer) 3
127.0.0.1:6379> lpop queue2
"user1"
127.0.0.1:6379> lpop queue2
"user2"
127.0.0.1:6379> llen queue2
(integer) 1
127.0.0.1:6379> LRANGE queue2 0 -1
1) "user3"
127.0.0.1:6379> LRANGE queue2 0 -1
1) "user3"
127.0.0.1:6379> lpush queue2 user2
(integer) 2
127.0.0.1:6379> lpush queue2 user1
(integer) 3
127.0.0.1:6379> LRANGE queue2 0 -1
1) "user1"
2) "user2"
3) "user3"
127.0.0.1:6379> del queue
(integer) 1
127.0.0.1:6379> lmove queue2 newqueue left left
"user1"
127.0.0.1:6379> lrange queue2 0 -1
1) "user2"
2) "user3"
127.0.0.1:6379> lrange newqueue 0 -1
1) "user1"
127.0.0.1:6379> lpush queue2 user1
(integer) 3
127.0.0.1:6379> lrange newqueue 0 -1
1) "user1"
127.0.0.1:6379> rpush queue2 user4
(integer) 4
127.0.0.1:6379> rpush queue2 user5
(integer) 5
127.0.0.1:6379> rpush queue2 user6
(integer) 6
127.0.0.1:6379> LRANGE queue2 0 -1
1) "user1"
2) "user2"
3) "user3"
4) "user4"
5) "user5"
6) "user6"
127.0.0.1:6379> LRANGE queue2 0 3
1) "user1"
2) "user2"
3) "user3"
4) "user4"
127.0.0.1:6379> LTRIM queue2 0 3
OK
127.0.0.1:6379> LRANGE queue2 0 -1
1) "user1"
2) "user2"
3) "user3"
4) "user4"
四、集合
集合(不包括重复元素的列表,但是集合本身是无序的【集合内元素的顺序不重要】)
127.0.0.1:6379> SADD set1 mem1 mem2 mem3 //设置集合
(integer) 3
127.0.0.1:6379> SRANDMEMBER set1 3 // 显示集合内所有元素
1) "mem3"
2) "mem2"
3) "mem1"
127.0.0.1:6379> SRANDMEMBER set1 5 // 长度大于集合本身大小 不会报错
1) "mem3"
2) "mem2"
3) "mem1"
127.0.0.1:6379> SCARD set1 // 获取集合长度
(integer) 3
127.0.0.1:6379> SRANDMEMBER set1 3 // 获取集合长度后,再查看集合内所有元素
1) "mem3"
2) "mem2"
3) "mem1"
127.0.0.1:6379> SREM set1 mem1 // 从集合中移除一个元素
(integer) 1
127.0.0.1:6379> SRANDMEMBER set1 3
1) "mem3"
2) "mem2"
127.0.0.1:6379> SISMEMBER set1 mem1 // 判断元素是否属于集合
(integer) 0
127.0.0.1:6379> SISMEMBER set1 mem3
(integer) 1
127.0.0.1:6379> SADD set2 mem3 mem1 mem6
(integer) 3
127.0.0.1:6379> SRANDMEMBER set1 3
1) "mem3"
2) "mem2"
127.0.0.1:6379> SRANDMEMBER set2 3
1) "mem3"
2) "mem6"
3) "mem1"
127.0.0.1:6379> SINTER set1 set2 // 两个集合相同元素
1) "mem3"
127.0.0.1:6379> SADD set2 mem3 mem2 // 重复添加相同元素时,集合内元素数量不增加
(integer) 1
127.0.0.1:6379> SRANDMEMBER set2 4
1) "mem3"
2) "mem2"
3) "mem6"
4) "mem1"
127.0.0.1:6379> SRANDMEMBER set1 4
1) "mem3"
2) "mem2"
127.0.0.1:6379> SDIFF set1 set2 // set1 对 set 2 求差集 结果为0
(empty array)
127.0.0.1:6379> SDIFF set2 set1 //set2 对 set1 求差集 有两个元素
1) "mem6"
2) "mem1"
有序集合
可以根据集合元素的分数设置排序的集合,注意集合内元素的顺序根据分数排序,只有分数相同的情况下,才会基于值的字典顺序排序。
适用于:
-
线上游戏,基于分数排名
-
速率限制,基于请求次数排序,限制异常高频访问
127.0.0.1:6379> ZADD sset1 60 tom 70 amy 32 ss
(integer) 3
127.0.0.1:6379> ZRANDMEMBER sset1 3- "amy"
- "tom"
- "ss"
127.0.0.1:6379> ZRANDMEMBER sset1 3 withscores - "amy"
- "70"
- "tom"
- "60"
- "ss"
- "32"
127.0.0.1:6379> ZADD sset1 67 amy 60 john // 更新amy分数 同时john的分数
// 与tom相同,按照字典排序
(integer) 1
127.0.0.1:6379> ZRANDMEMBER sset1 5 - "amy"
- "tom"
- "john"
- "ss"
127.0.0.1:6379> ZRANDMEMBER sset1 5 withscores - "amy"
- "67"
- "tom"
- "60"
- "john"
- "60"
- "ss"
- "32"
127.0.0.1:6379> ZRANGE sset1 0 -1 withscores // 升序列出所有 - "ss"
- "32"
- "john"
- "60"
- "tom"
- "60"
- "amy"
- "67"
127.0.0.1:6379> ZREVRANGE sset1 0 -1 withscores // 降序列出所有 - "amy"
- "67"
- "tom"
- "60"
- "john"
- "60"
- "ss"
- "32"
127.0.0.1:6379> ZRANGEBYSCORE sset1 30 60 withscores //分数在30-60 的元素 - "ss"
- "32"
- "john"
- "60"
- "tom"
- "60"
127.0.0.1:6379> ZRANGEBYSCORE sset1 50 60 withscores // 分数在50-60的元素 - "john"
- "60"
- "tom"
- "60"
127.0.0.1:6379> ZRANK sset1 amy // 指定元素 升序排名
(integer) 3
127.0.0.1:6379> ZREVRANK sset1 amy // 指定元素 降序排名
(integer) 0 // 排名从零开始
127.0.0.1:6379> ZINCRBY sset1 30 ss // zadd直接调整现有分数ZINCRBY 在现有分数上做加法
"62"
127.0.0.1:6379> ZRANGE sset1 0 -1 - "john"
- "tom"
- "ss"
- "amy"
127.0.0.1:6379> ZRANGE sset1 0 -1 withscores - "john"
- "60"
- "tom"
- "60"
- "ss"
- "62"
- "amy"
- "67"
四、数据流
类似于只能新增的日志,redis会给数据流的每一个单独的信息设置唯一的ID,基于id对数据流信息进行处理,
使用场景:
- 事件追踪:用户操作比如说鼠标点击
- 传感器监控:读取设备信息
- 用户提醒:不同用户的提示信息,可以保存到不同的数据流中
XADD 新增数据流信息
XREAD 读取数据流信息
XRANGE 两个信息ID之间一共有多少个消息
XLEN 数据流的完整长度
每一个消息ID默认基于时间生成,所有ID值不同是正常的
127.0.0.1:6379> XADD game_event * player player1 speed 150km/h rank 1
"1725247886395-0" // 第一条消息ID
127.0.0.1:6379> XADD game_event * player player2 speed 100km/h rank 2
"1725247898840-0"
127.0.0.1:6379> XADD game_event * player player3 speed 99km/h rank 3
"1725247913980-0"
127.0.0.1:6379> XADD game_event * player player4 speed 94km/h rank 4
"1725247923881-0"
127.0.0.1:6379> XRANGE game_event 1725247886395-0 + //从第一条信息输出所有
1) 1) "1725247886395-0"
2) 1) "player"
2) "player1"
3) "speed"
4) "150km/h"
5) "rank"
6) "1"
2) 1) "1725247898840-0"
2) 1) "player"
2) "player2"
3) "speed"
4) "100km/h"
5) "rank"
6) "2"
3) 1) "1725247913980-0"
2) 1) "player"
2) "player3"
3) "speed"
4) "99km/h"
5) "rank"
6) "3"
4) 1) "1725247923881-0"
2) 1) "player"
2) "player4"
3) "speed"
4) "94km/h"
5) "rank"
6) "4"
127.0.0.1:6379> XLEN game_event //查看game_event 存储多少条记录
(integer) 4
127.0.0.1:6379> XRANGE game_event 1725247886395-0 + COUNT 2 // 从第一条消息开始,只显示两条
1) 1) "1725247886395-0"
2) 1) "player"
2) "player1"
3) "speed"
4) "150km/h"
5) "rank"
6) "1"
2) 1) "1725247898840-0"
2) 1) "player"
2) "player2"
3) "speed"
4) "100km/h"
5) "rank"
6) "2"
127.0.0.1:6379> XREAD count 10 BLOCK 300 STREAMS game_event $ // 从game_event 中读取10次,如果没有新的写入,则阻塞300ms, $ 可以替换为消息ID $ 代表的是指定数据流的最后一个信息
// 将上一条指令的$替换为player2的消息ID ,则从player2 下一条消息开始输出
127.0.0.1:6379> XREAD count 100 BLOCK 300 STREAMS game_event 1725247898840-0
1) 1) "game_event"
2) 1) 1) "1725247913980-0"
2) 1) "player"
2) "player3"
3) "speed"
4) "99km/h"
5) "rank"
6) "3"
2) 1) "1725247923881-0"
2) 1) "player"
2) "player4"
3) "speed"
4) "94km/h"
5) "rank"
6) "4"
五、地理空间
使用经纬度表示地理位置,先写经度(-180~180) 再写维度(-90~90)。
东经为正 西经为负 北纬为正 南纬为负
127.0.0.1:6379> GEOADD site1 -122.27652 37.805186 station:1 //site1 坐标1
(integer) 1
127.0.0.1:6379> GEOADD site1 -122.2674626 37.8062344 station:2 //site1 坐标2
(integer) 1
127.0.0.1:6379> GEOADD site1 -122.2469854 37.8104049 station:3 //site1 坐标3
(integer) 1
127.0.0.1:6379> GEOSEARCH site1 FROMLONLAT -122.2612767 37.7936847 BYRADIUS 5 km WITHDIST //site1 距离给定坐标5千米的点位,同时返回每个点位距离给定坐标的具体距离
1) 1) "station:1"
2) "1.8523"
2) 1) "station:2"
2) "1.4979"
3) 1) "station:3"
2) "2.2441"