redis 进阶篇
1. redis事务
1.1mysql事务与redis事务区别:
-
mysql事务(基于日志):原子性,一致性(要么同时成功,要么同时失败)
MySQL:MySQL会默认开启一个事务,且缺省设置是自动提交,即,每成功执行一个SQL,一个事务就会马上 COMMIT。所以不能Rollback。
-
redis事务(基于队列):redis单条命令保证原子性,但是事务不保证原子性
Redis:默认不会开启事务,即command会立即执行,而不会排队。并不支持Rollback
1.2 redis 事务
-
redis的事务本质:一组命令的集合,一个事务中所有的命令都会被序列化
-
redis的事务:开始事务(multi),命令入队列,执行事务(exec)
-
discard:取消事务
2. redis实现乐观锁(面试常问)
监控:watch,一般会使用乐观锁,悲观锁使用较少
- 乐观锁:watch更新数据时去判断version,在此期间是否有人修改过这个数据
- 测试多线程修改值,用watch当做乐观锁操作,事务正常结束数据没有发生变动则执行成功,如果在事务期间数据发生了变动则执行失败
- 加锁:watch,解锁:unwatch(exec/discard自动解锁)
3. jedis
3.1 jedis简介
-
jedis是redis官方推荐的java连接开发工具
-
实际是使用java来操作redis的jar包
3.2 通过jedis操作redis
- 导入jedis,fastjson依赖
- 连接阿里云redis:连接远程redis注意事项
- 常用的API:五大数据类型,三种特殊类型的命令
ctrl+alt+win+t(surround with):if,while,try catch等快捷键
4.springboot集成redis
4.1 操作步骤
-
创建springboot项目在nosql选项中勾选redis
-
spring2.x过后,原来使用的jedis被替换成了lettuce
-
jedis:采用的直连,多个线程操作不安全,BIO(阻塞式)
-
lettcue:采用netty,实例可以在多个线程中共享,线程安全,NIO(非阻塞式)
-
配置连接:配置host,以及端口
-
编写测试:使用redistemplate
External libraries里面查看autoconfigure里面与redis相关的配置
4.2 自定义redistemplate模板
使用jackson的objectMapper方法可以实现java对象与json格式之间的相互转换
-
java序列化:就是指把java对象转化成字符序列的过程(反序列化则相反)
-
如果没有使用序列化则需要使用jackson转换成json
-
在企业中我们所有的pojo都会序列化(implements Serializable)
-
默认的jdk序列化方式,可以自己在redisconfig配置序列化方式
-
使用自定义的redisutil(hutool-java工具包)
5.Redis持久化
5.1 RDB(Redis Data Base)
- 在指定时间间隔将内存中的数据集写入磁盘(通过子进程进行fork)
- rdb保存的文件是dump.rdb文件
- save规则满足的情况下,会自动出发rdb规则
- 执行flushall命令,也会触发rdb规则
- 退出redis,也会产生rdb文件
- 如果存在dump.rdb文件,启动就会自动检查恢复数据
- 适合大规模的数据恢复(优点)
- fork进程的时候会占用一定的内容空间(缺点)
RDB比AOF更加高效大部分情况都是使用RDB,不需要修改配置,AOF默认不开启
5.2 AOF(Append Only File)
- 将我们的所有命令记录下来,恢复的时候就把这个文件再执行
- aof保存的文件是appendonly.aof文件
- aof默认是关闭的,appendonly no改为yes则开启了aof
- aof文件如果有错,redis则无法启动,redis-check-aof可以修复aof文件
aof文件远远大于rdb,修速度也比rdb慢,所以redis默认持久化方案为rdb
6. Redis(发布订阅)
- 消息发送者,频道,订阅者(redis也可以做发布订阅)
- activemq/rabbitmq消息队列进行复杂场景的处理
- subscribe:订阅指定频道的信息(订阅者)
- publish:发布消息到频道(发布者)
- 这些命令被广泛应用与即时通讯,网络聊天,实时广播等
8.主从复制
8.1主从复制概念
- 将一台redis服务器的数据,复制到其它redis服务器,数据的复制是单向的,主机进行写入,从机负责读取,大部分情况下都是在读取(读写分离)
8.2 主从复制的主要作用
-
数据冗余:实现了数据热备份,是持久化之外的方式
-
故障恢复:当主节点出现故障时,由从节点提供服务快速恢复
-
负载均衡:读写分离,主节点提供写服务,从节点提供度服务,分担服务器负载,尤其在写少读多的情况下大大提高redis的并发量
8.3 环境配置
- info replication:查看当前库的复制信息
- 1:修改端口(三个redis不同的端口配置)
- 2:pidfile后台进程文件,根据端口配置
- 3:logfile日志文件,根据端口配置
- 4:rdb文件,根据端口配置
每台redis服务器都是主节点,一般情况下只用配置从机就好,正式的主从配置在配置文件中进行,使用命令配置主从只是暂时的
8.4 复制原理
-
slaceof 127.0.0.1 6379:认6379为主机
-
主机才可以写,主机中所有的信息和数据都会同步到从机
-
Slave 启动成功连接到 master 后会发送一个sync同步命令
-
Master 接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行
-
完毕之后,master将传送整个数据文件到slave,并完成一次完全同步。
-
全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
-
增量复制:Master 继续将新的所有收集到的修改命令依次传给slave,完成同步
-
只要是重新连接master,一次完全同步(全量复制)将被自动执行!
如果主机断开连接,可以使用slaveof no one 让主机变成主机(手动选老大)
9.哨兵模式(面试常问)
9.1 基本概念
解决问题:当主服务器宕机后,需要手动将一台服务器切换为主服务器,这就需要人工干预,还会造成一段时间内服务不可用,所以有了哨兵模式
- 自动选择老大模式
- 通过发送命令等待服务器响应,从而监控运行多个redis实例
- 单个哨兵监控redis服务可能出现问题,则出现了多哨兵模式
假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover[故障转移]操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。
9.2 哨兵配置
-
配置哨兵文件sentinel.conf
sentinel monitor 被监控的名称 host port 1 sentinel monitor myredis 127.0.0.1 6379 1
-
后面的这个数字1,代表主机挂了,slave投票看让谁接替成为主机,票数最多的,就会成为主机!
-
启动哨兵:redis-sentinel kconfig/sentinel.conf
-
哨兵模式,基于主从复制模式,所有主从复制的优点都有
-
主从可以切换,故障可以转移,系统可用性好
-
哨兵模式就是主从模式的升级,手动到自动
10. 缓存穿透和雪崩
面试高频,工作常用
10.1 缓存穿透
10.1.1 缓存穿透的概念
用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中(秒杀),于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
查不到数据,却一直查询
10.1.2 缓存穿透的解决方案
-
布隆过滤器:在控制层进行校验,不符合规则就丢弃,从而避免了对底层存储系统的查询压力
-
缓存空对象:在缓存中加入一个空值并设置过期时间,之后再访问会从缓存中获取,保护了后端数据源
10.2 缓存击穿
10.2.1 缓存击穿的概念
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。
查询量太大,缓存过期,将所有请求砸在数据库上,导致缓存击穿
10.2.2 缓存击穿的解决方案
- 设置热点数据永不过期
- 分布式锁:对应每一个key,同时只有一个线程去查询后端服务,其它线程没有获得权限,只有等待
分布式锁的方式,将高并发的压力全部转移到分布式锁上,对分布式锁的考验很大
10.3 缓存雪崩
10.3.1 缓存雪崩概念
- 概念:是指在某一段时间段,缓存集中过期失效,redis宕机,断电断网等致命雪崩
10.3.2 缓存雪崩解决方案
-
异地多活:既然redis可能挂掉,那就多增设几台redis
-
限流降级:
关闭某些服务,是其它服务可用
通过加锁或队列来控制读数据库写缓存的线程数量
-
数据预热:设置缓存的不同失效时间,让缓存失效的时间点尽量均匀