Redis数据库
关系型数据库:MySQL,支持表结构
非关系型数据库:Redis,可以使用键值对。
非关系型数据库的分类
基于键值对key-value类型:Redis,memcached
列存储数据库Column-oriented Graph:HBase
图形数据库 Graphs based:Neo4j
文档型数据库:MongoDB
MongoDB是一个基于分布式文件存储的数据库,主要用来处理大量的文档。
Redis概念
远程字典服务器,开源的,C编写的,高性能的。用途: 数据库、缓存、消息中间件。
redis中文官网:http://www.redis.cn/
redis英文官网:https://redis.io/
Redis的特性
1.持久化
2.支持丰富的数据类型
3.数据的备份。主从复制
Redis的优点
1.性能高 读11w/s 写8.1w/s
2.支持丰富的数据类型,string、set、hash、zset、list
3.原子性 redis的操作是原子的,但是事务没有原子性
4.丰富的特性 发布订阅、key过期
Redis的命令与数据类型
#数据库的切换
select + index #select 1
#查看数据库的大小
dbsize
#查看key值
keys * #*匹配任意个字符
keys k? #?匹配一个字符
删除key
del key
#数据库的清空
FLUSHDB #清除当前数据库
flushall #把所有数据库清空
#判断key是否存在
Exists + key
#把key从当前库移动到目标库
Move key [num]
#查看key的类型
Type key
#为给定的key设置过期的时间
Expire key seconds #expire k1 10
#查看某个key的剩余时间 看还有多少存活时间
ttl+key #-1代表永不过期 ,-2代表已经过期
数据类型
string数据类型
二进制安全的,可以存任何数据
#设定指定key的值
set key value
#获取指定key的值
get key
#获取设置多个给定的key值
mset key1 value1 key2 value2
mget k1 k2
#二进制安全的体现(理解)
set k22 hello\0world
get k22
"hello\\0world"
#返回字符串的子串
GETRANGE key start end
getrange k4 0 -1 #-1代表倒数第一个
#用value覆盖字符串的值,从offset开始
SETRANGE key offset value
#将给定key的值设为value ,并返回key的旧值(old value)。
GETSET key value
#设置新值的同时设置过期时间
SETEX k1 10 200
#累加命令(value 一定要是数值)
INCRBY key value #每次加value
incr key #每次加1
list数据类型
双向链表
#在链表的两端进行插入和删除
lpush/rpush
lpop/rpop
#查找范围
lrange list1 0 -1 #-1代表倒数第一个
#list 支持下标访问
lset key index value #lset list1 5 1000
LINDEX key index
#修剪得命令(删除范围以外的数据)
ltrim list1 2 5
set数据类型
元素是唯一得 但是没有顺序,底层使用得哈希表
#添加元素得命令
sadd key value1 value2
#遍历的方式
smembers key
#查看元素的个数
scard key
#随机获取(删除)几个数
SRANDMEMBER myset2 2
spop myset2 2
#取交集、差集、并集
sinter/ sdiff/ sunion
sort set 数据类型
可以在元素的面前增加一个权重值,然后根据权重进行排序
#元素的添加
zadd key double1 value1 double2 value2
#遍历的命令
zcount zset1 10 20
(integer)2
zrange zset1 0 1
"hello"
"wangdao"
zrange zset1 0 1 withscores
"hello"
"10"
"wangdao"
"20"
zadd zset2 10 wuhan 10 wangdao 10 hello 10 world
(integer)4
zrangebylex zset2 [h [wu
"hello"
"wangdao"
"world"
hash数据类型(重要)
等价于map<key1,map<key2,value>>
#设置与获取
hset people name wangdao sex man age 100
hget
#获取key
hkeys people
“name"
"sex"
"age"
#获取value
hvals people
“wangdao”
“man”
配置文件
1.进入目录(路径) cd /etc/redis/ #配置文件路径
2.redis-cli
3.看进程起没起起来
ps -elf | grep redis
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bNlOVr9a-1689341827072)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20230713141312451.png)]
4.关闭redis服务器
进入redis-cli之后
输入shutdown
然后再输入ping 发现ping不通就对了
5.redis-server 启动redis
然后再输入ping 发现返回pong就说明服务器被起起来了
启动redis服务器的方式
redis-server+指定路径(如果权限不够在前面加上sudo)
持久化(重要)
将redis数据库中的数据从内存保存到磁盘中。优点:断电重启之后,数据不会丢失。
1.两种类型
1.RDB持久化:将Redis中的数据定期dump到磁盘中。默认的持久化方式。
2.AOF持久化:将所有的写命令备份到磁盘中,主流的持久化方式。
2.RDB持久化
RDB是Redis默认的持久化方案。在指定的时间间隔内,执行指定次数的写操作,则会内存中的数据写入磁盘中。即在指定目录下生成一个dump.rdb文件,文件路径:/var/lib/redis/6379
触发快照的方式
1.shutdown与flushall都可以触发快照,但是意义不大,可以忽略
2.可以使用save手动触发快照
3.在指定的时间间隔内,执行指定次数的写操作
save 30 2#要保证时间到达,并且写次数也要满足,就是同时满足时间与写的次数
优缺点
优点
1.适合大规模的数据恢复,与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些
2.如果业务对数据完整性和一致性要求不高,RDB是很好的选择。
缺点
1.数据的完整性和一致性不高,因为RDB可能在最后一次备份时宕机了。
2.备份时占用内存,因为Redis在备份时会独立创建一个fork子进程,将数据写入到一个临时文件(此时内存中的数据是原来的两倍),最后再讲临时文件替换成之前的备份文件
AOF持久化
AOF方式是将执行过的写指令巨鹿下来并重新执行一次
appendfsync always #一直同步
appendfsync everysec #每秒同步一次(默认)
appendfsync no #从不同步
重写
set k1 1
incr k1
incr k1
incr k1
incr k1 #连续执行了99次 #k1 100
set k1 100
手动执行BGREWRITEAOF也可以达到重写效果
#Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
优缺点
优点:保证数据的完整性和一致性。
缺点:大量数据回复的时候,执行时间比较长;文件的大小比较大
问题
1.默认采用的是rdb持久化的方式。流行的是aof持久化方式
2.两种持久化方式是可以同时存在的。互相弥补对方的缺点。两种都存在的时候,会以rdb进行持久化
3.如果只有aof持久化的方式,并且aof文件损坏,那么redis服务器是无法启动的
4.sudo redis-check-aof --fix appendonly.aof可以进行aof文件损坏的修复
Redis的事务
redis的事务是一种操作的集合,但是redis的事务是没有原子性的。
#开启事务
multi
#提交事务
exec
#取消事务
discard
#监视某个变量
watch
#取消监视
unwatch
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X240hklE-1689341827073)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20230713100702992.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-68m1iyUO-1689341827074)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20230713101600740.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gtKM58Hl-1689341827075)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20230713101923996.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J1okhSTg-1689341827076)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20230713102926430.png)]
可以将incr k2 看成运行时出错了,而set k3 是编译时,语法不支持,编译报错了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E8ci74Dm-1689341827077)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20230713114008199.png)]
悲观锁:每次拿数据的时候都会先上锁。
:乐观锁每次拿数据的时候,认为数据不会被修改,所以就不会上锁。(版本号机制或CAS)
事务的特性
1.没有原子性
2.没有隔离级别的说法(MySQL对比的)
3.单独的隔离操作
Redis主从复制
概念
主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。
配置步骤
1.在/etc/redis下面,将6379.conf拷贝两份,分别叫做6380.conf,6381.conf
2.修改6380.conf与6381.conf中的配置信息
#port port 6380
#pidfile pidfile "/var/run/redis_6379.pid"
#logfile logfile "/var/run/redis_6379.log"
#dump.rdb dbfilename "dump6380.rdb"
#appendonly.aof appendfilename "appendly6380.aof"
3.分别将上述三个文件进行启动(三台服务器就启动了)
sudo redis-server /etc/redis/6379.conf
sudo redis-server /etc/redis/6380.conf
sudo redis-server /etc/redis/6381.conf
可以使用ps -elf | grep redis 进行查看
4.分别进行对应的客户端
redis-cli -p 6379
redis-cli -p 6380
redis-cli -p 6381
5.执行 info replication 查看主从复制信息,发现默认情况下,三个都是主机(默认的都是主节点)
6.现在将6379作为主机,想将6380与6381作为6379的从机,需要在6380和6381下面,直接执行slaveof 127.0.0.1 6390,此时6380与6381就成了6379的从机,仍然可以使用info replication 查看主从复制的信息,发现6380与6381的身份变成了slave
问题:
1.主机上有数据更新的时候,会将数据同步到从机上;但是从机上是不能修改数据的
2.将6379作为6380的主机,将6380作为6381的主机,此时6380仍然体现的是从机的身份,也是不能进行写操作的。
3.如果6379挂掉了,那么两个从机6380和6381会一直等着主人6379上线,不会做任何操作,直到6379上线之后,两个从机会立马连接到主机6379上,此处会有缺陷,如果主人挂了之后,不能进行写操作。
哨兵模式
会使用留言协议(造谣)与投票协议(少数服从多数)
配置方式
1.在/etc/redis下面,写一个配置文件
sentinel monitor master6379 127.0.0.1 6379 1
#让哨兵去见识主机6379 ,等待主机的状态变化
2.启动哨兵模式
sudo redis-sentinel /etc/redis/sentinel.conf
此时,哨兵会负责监视主机,当主机挂掉以后,会进行留言协议与投票协议,最后将一票投给6381,此时6381成为了新的主机,而6380是6381的从机
#sentinel monitor {masterName} {masterIp} {masterPort} {quorum}
#sentinel monitor 主节点名称 主节点Ip 主节点端口 投票数
#quorum是判断主节点客观下线的哨兵数量阈值
#当判断主节点下线的哨兵数量达到quorum时,对主节点进行客观下线
#建议取消为哨兵数量的一半加1
#generated by config rewrite
#Generated by CONFIG REWRITE
sentinel monitor master6379 127.0.0.1 16379 1
#服务器启动
sudo redis-server /etc/redis/6381.conf
#进入服务器
redis-cli -p 6380
查看主从复制信息
info replication
Redis常见问题
1.缓存雪崩
大量数据在同一时间失效,当多个客户端请求数据的时候,就不会在混村中获取数据,此时就必须要在底层数据库中进行查询,导致数据库的压力非常大。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XAZmFxkN-1689341827077)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20230713203916616.png)]
解决方案:1.分散数据的过期时间 2.让数据不过期
2.缓存击穿
某个热点数据在缓存中失效了,大量访问同时请求这个数据,就会将查询下撑到数据库层,会导致底层数据库的压力非常大。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZlpRQcmL-1689341827078)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20230713204710525.png)]
解决方案:1.延长key的过期时间或者设置为永不过期 2.可以对数据库加锁,只有得到锁的请求可以访问数据库
3.缓存穿透
访问的数据在缓存中不存在,并且在底层数据库中也不存在,就在访问一个本来就不存在的数据。大量访问同时请求这个数据,就会将查询下沉到数据库层,会导致底层数据库压力非常大。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bsABU8P7-1689341827079)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20230713205252287.png)]
解决方案:可以在缓存中设置map数据类型,map<key,null>,这样在缓存中找到key后检查对应的value即可。