职业学院网站建设,网站建设面试,logo在线设计生成器app,免费建站并且绑定域名第一章 Redis 事务
1.1 节 数据库事务复习
数据库事务的四大特性
A#xff1a;Atomic #xff0c;原子性#xff0c;将所以SQL作为原子工作单元执行#xff0c;要么全部执行#xff0c;要么全部不执行#xff1b;C#xff1a;Consistent#xff0c;一致性#xff0…第一章 Redis 事务
1.1 节 数据库事务复习
数据库事务的四大特性
AAtomic 原子性将所以SQL作为原子工作单元执行要么全部执行要么全部不执行CConsistent一致性事务完成后所有的数据的状态都是一致的。即A账户只要减去100B账户就必定增加100IIsolation隔离性如果有多个事务并发执行每个事务做出的修改必须与其他事务隔离DDuration持久性即事务完成后对数据库数据的修改被持久化存储
1.2 节 Redis 事务介绍
Redis事务是一组命令的集合一个事务中的所有命令都将被序列化按照一次性、顺序性、排他性的执行一系列的命令。
Redis事务三大特性 单独的隔离操作事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中不会被其他客户端发送来的命令请求所打断 没有隔离级别的概念队列中的命令没有提交之前都不会实际的被执行因为事务提交前任何指令都不会被实际执行也就不存在”事务内的查询要看到事务里的更新在事务外查询不能看到”。 不保证原子性redis同一个事务中如果有一条命令执行失败其后的命令仍然会被执行没有回滚
1.3 节 Redis 事务的基本操作
Multi、Exec、discard
示例1正常执行
127.0.0.1:6379 multi
OK
127.0.0.1:6379(TX) set k1 1
QUEUED
127.0.0.1:6379(TX) get k1
QUEUED
127.0.0.1:6379(TX) incr k1
QUEUED
127.0.0.1:6379(TX) get k1
QUEUED
127.0.0.1:6379(TX) exec
1) OK
2) 1
3) (integer) 2
4) 2
示例2放弃事务
127.0.0.1:6379 multi
OK
127.0.0.1:6379(TX) set k2 1
QUEUED
127.0.0.1:6379(TX) get k2
QUEUED
127.0.0.1:6379(TX) incr k2
QUEUED
127.0.0.1:6379(TX) get k2
QUEUED
127.0.0.1:6379(TX) discard
OK
示例3全部都不执行
127.0.0.1:6379 multi
OK
127.0.0.1:6379(TX) set k3 1
QUEUED
127.0.0.1:6379(TX) get k3
QUEUED
127.0.0.1:6379(TX) set k3
(error) ERR wrong number of arguments for set command
127.0.0.1:6379(TX) exec
(error) EXECABORT Transaction discarded because of previous errors
注意
命令集合中含有错误的指令注意是语法错误全部失败。
示例4运行时错误
127.0.0.1:6379 multi
OK
127.0.0.1:6379(TX) set k4 1
QUEUED
127.0.0.1:6379(TX) incr k4
QUEUED
127.0.0.1:6379(TX) get k4
QUEUED
127.0.0.1:6379(TX) set name zhangsan
QUEUED
127.0.0.1:6379(TX) incr name
QUEUED
127.0.0.1:6379(TX) get name
QUEUED
127.0.0.1:6379(TX) exec
1) OK
2) (integer) 2
3) 2
4) OK
5) (error) ERR value is not an integer or out of range
6) zhangsan
注意 运行时错误即非语法错误正确命令都会执行错误命令返回错误。 Redis有三种集群模式 主从模式 Sentinel模式 Cluster模式
第二章 Redis 主从复制
2.1 节 Redis 主从复制概述
什么是主从复制
主从复制是指将一台Redis服务器的数据复制到其他的Redis服务器。前者称为主节点(master)后者称为从节点(slave),数据的复制是单向的只能由主节点到从节点。
主从复制的作用 数据冗余主从复制实现了数据的热备份是持久化之外的一种数据冗余方式。 故障恢复当主节点出现问题时可以由从节点提供服务实现快速的故障恢复实际上是一种服务的冗余。 负载均衡在主从复制的基础上配合读写分离可以由主节点提供写服务由从节点提供读服务 即写Redis数据时应用连接主节点读Redis数据时应用连接从节点分担服务器负载尤其是在写少读多的场景下通过多个从节点分担读负载可以大大提高Redis服务器的并发量。 高可用基石除了上述作用以外主从复制还是哨兵和集群能够实施的基础因此说主从复制是Redis高可用的基础。
2.2 节 Redis 主从复制搭建
在一台虚拟机上搭建
新建redis6379.conf
内容
include /usr/local/redis/redis.conf
pidfile /var/run/redis_6379.pid
port 6379
dbfilename dump6379.rdb
同理
新建redis6380.conf
include /usr/local/redis/redis.conf
pidfile /var/run/redis_6380.pid
port 6380
dbfilename dump6380.rdb
新建redis6381.conf
include /usr/local/redis/redis.conf
pidfile /var/run/redis_6381.pid
port 6381
dbfilename dump6381.rdb
【2】启动三台redis服务器
redis-server ./redis6379.conf
redis-server ./redis6380.conf
redis-server ./redis6381.conf
【3】查看系统进程
ps -ef |grep redis 会有已经运行的进程
root 122739 1 0 00:18 ? 00:00:00 redis-server 0.0.0.0:6379
root 122877 1 0 00:18 ? 00:00:00 redis-server 0.0.0.0:6380
root 122965 1 0 00:19 ? 00:00:00 redis-server 0.0.0.0:6381
root 123210 3414 0 00:19 pts/0 00:00:00 grep --colorauto redis
【4】查看三台主机运行情况 info replication 查看节点相关信息
#打印主从复制的相关信息
./redis-cli -p 6379
./redis-cli -p 6380
./redis-cli -p 6381
127.0.0.1:6379 info replication
127.0.0.1:6380 info replication
127.0.0.1:6381 info replication
【5】配从库不配主库
slaveof ip port
示例在6380和6381上执行
127.0.0.1:6380 SLAVEOF 192.168.184.100 6379
OK
【6】在主机上写在从机上可以读取数据
set k1 v1
2.3 节 Redis 主从复制原理
主从复制可以分为3个阶段 连接建立阶段即准备阶段 数据同步阶段 命令传播阶段
复制过程大致分为6个过程 保存主节点master信息。 从节点slave内部通过每秒运行的定时任务维护复制相关逻辑当定时任务发现存在新的主节点后会尝试与该节点建立网络连接 从节点与主节点建立网络连接 从节点会建立一个 socket 套接字从节点建立了一个端口为51234的套接字专门用于接受主节点发送的复制命令 发送ping命令 连接建立成功后从节点发送 ping 请求进行首次通信。 权限验证。 如果主节点设置了 requirepass 参数则需要密码验证从节点必须配置 masterauth 参数保证与主节点相同的密码才能通过验证如果验证失败复制将终止从节点重新发起复制流程。 同步数据集。 主从复制连接正常通信后对于首次建立复制的场景主节点会把持有的数据全部发送给从节点这部分操作是耗时最长的步骤。 主从同步策略 主从刚刚连接的时候进行全量同步全同步结束后进行增量同步。当然如果有需要 slave 在任何时候都可以发起全量同步。 redis 策略是无论如何首先会尝试进行增量同 步如不成功要求从机进行全量同步。
第三章 Redis 哨兵监控
3.1 节 Redis哨兵概述
主从复制的缺点当主机 Master 宕机以后我们需要人工解决切换
哨兵概述
哨兵模式是一种特殊的模式首先Redis提供了哨兵的命令哨兵是一个独立的进程作为进程它会独立运行。其原理是哨兵通过发送命令等待Redis服务器响应从而监控运行的多个Redis实例。 哨兵作用 集群监控负责监控redis master和slave进程是否正常工作 消息通知如果某个redis实例有故障那么哨兵负责发送消息作为报警通知给管理员 故障转移如果master node挂掉了会自动转移到slave node上 配置中心如果故障转移发生了通知client客户端新的master地址
3.2 节 Redis哨兵搭建
【1】编写配置文件
新建sentinel-26379.conf文件
#端口
port 26379
#守护进程运行
daemonize yes
#日志文件
logfile 26379.log
sentinel monitor mymaster 192.168.184.100 6379 2
参数解释
sentinel monitor mymaster 192.168.92.128 6379 2 配置的含义是该哨兵节点监控192.168.92.128:6379这个主节点该主节点的名称是mymaster最后的2的含义与主节点的故障判定有关至少需要2个哨兵节点同意才能判定主节点故障并进行故障转移。
同理
新建sentinel-26380.conf文件
#端口
port 26380
#守护进程运行
daemonize yes
#日志文件
logfile 26380.log
sentinel monitor mymaster 192.168.184.100 6379 2
新建sentinel-26381.conf文件
#端口
port 26381
#守护进程运行
daemonize yes
#日志文件
logfile 26381.log
sentinel monitor mymaster 192.168.184.100 6379 2
【2】启动哨兵节点
redis-sentinel sentinel-26379.conf
redis-sentinel sentinel-26380.conf
redis-sentinel sentinel-26381.conf
【3】查看哨兵状态 先进入哨兵客户端
redis-cli -p 26379查看哨兵信息
info sentinel# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:namemymaster,statusok,address192.168.9.133:6379,slaves2,sentinels3 sentinel_masters:1 该哨兵为主节点 address192.168.9.133:6379 监控的ip slaves2 有两个从节点 sentinels3 总共有三个哨兵监控
【4】测试故障转移使用kill命令杀掉主节点 查看所有服务
ps -ef | grep redis 根据id杀死6379进程
kill -9 进程id 哨兵会重新票选新的主节点注意需要等待一定的时间 【5】查看哨兵节点信息
info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:namemymaster,statusok,address192.168.9.133:6380,slaves2,sentinels3 监听的ip变成了63806380变成了新的主节点
3.3 节 Redis 哨兵原理
3.3.1 监控阶段
注意 sentinel(哨兵1)-----向master(主)和slave(从)发起info拿到全信息。 sentinel(哨兵2)-----向master(主)发起info就知道已经存在的sentinel(哨兵1)的信息并且连接slave(从)。 sentinel(哨兵2)-----向sentinel(哨兵1)发起subscribe(订阅)。
3.3.2 通知阶段
sentinel不断的向master和slave发起通知收集信息。
3.3.3 故障转移阶段
通知阶段sentinel发送的通知没得到master的回应就会把master标记为SRI_S_DOWN,并且把master的状态发给各个sentinel其他sentinel听到master挂了说我不信我也去看看并把结果共享给各个sentinel当有一半的sentinel都认为master挂了的时候就会把master标记为SRI_0_DOWN。
3.3.4 投票阶段
方式 自己最先接到哪个sentinel的竞选通知就会把票投给它。
剔除一些情况 不在线的 响应慢的 与原来master断开时间久的 优先级原则
第四章 Redis Cluster
完善哨兵模式的缺点 当master挂掉的时候sentinel 会选举出来一个 master选举的时候是没有办法去访问Redis的会存在访问瞬断的情况 哨兵模式对外只有master节点可以写slave节点只能用于读。尽管Redis单节点最多支持10W的QPS但是在电商大促的时候写数据的压力全部在master上。 Redis的单节点内存不能设置过大若数据过大在主从同步将会很慢在节点启动的时候时间特别长
4.1 节 Redis Cluster概述
Redis集群的优点 Redis集群有多个master可以减小访问瞬断问题的影响 Redis集群有多个master可以提供更高的并发量 Redis集群可以分片存储这样就可以存储更多的数据
4.2 节 Redis Cluster模式搭建
Redis的集群搭建最少需要3个master节点我们这里搭建3个master每个下面挂一个slave节点总共6个Redis节点
【1】 准备环境 三个linux虚拟机
第1台机器 192.168.9.131 8001端口 8002端口
第2台机器 192.168.9.132 8001端口 8002端口
第3台机器 192.168.9.133 8001端口 8002端口
拷贝配置文件
将redis安装目录下的 redis.conf 文件分别拷贝到8001和8002目录下
cp /usr/local/redis-6.2.6/redis.conf /usr/local/redis-cluster/8001
cp /usr/local/redis-6.2.6/redis.conf /usr/local/redis-cluster/8002
修改redis.conf文件以下内容 8001
# 端口
port 8001
# 后台启动
daemonize yes
# 进程id
pidfile /var/run/redis_8001.pid
#指定数据文件存放位置必须要指定不同的目录位置不然会丢失数据
dir /usr/local/redis-cluster/8001/
#启动集群模式
cluster-enabled yes
#集群节点信息文件这里800x最好和port对应上
cluster-config-file nodes-8001.conf
# 节点离线的超时时间
cluster-node-timeout 5000
#去掉bind绑定访问ip信息
#bind 127.0.0.1
#关闭保护模式
protected-mode no
#启动AOF文件
appendonly yes
#如果要设置密码需要增加如下配置
#设置redis访问密码
#requirepass 123456
#设置集群节点间访问密码跟上面一致
#masterauth 123456
修改redis.conf文件以下内容 8002
# 端口
port 8002
# 后台启动
daemonize yes
# 进程id
pidfile /var/run/redis_8002.pid
#指定数据文件存放位置必须要指定不同的目录位置不然会丢失数据
dir /usr/local/redis-cluster/8002/
#启动集群模式
cluster-enabled yes
#集群节点信息文件这里800x最好和port对应上
cluster-config-file nodes-8002.conf
# 节点离线的超时时间
cluster-node-timeout 5000
#去掉bind绑定访问ip信息
#bind 127.0.0.1
#关闭保护模式
protected-mode no
#启动AOF文件
appendonly yes
#如果要设置密码需要增加如下配置
#设置redis访问密码
#requirepass 123456
#设置集群节点间访问密码跟上面一致
#masterauth 123456
三台机器同理
【3】启动集群
每台机器都启动服务器
redis-server /usr/local/redis-cluster/8001/redis.conf
redis-server /usr/local/redis-cluster/8002/redis.conf
创建集群
redis-cli -a redis-pw --cluster create --cluster-replicas 1
192.168.9.131:8001 192.168.9.131:8002
192.168.9.132:8001 192.168.9.132:8002
192.168.9.133:8001 192.168.9.133:8002 没有密码去掉 -a redis -pw
查看帮助命令 src/redis‐cli --cluster help
参数 create创建一个集群环境host1:port1 ... hostN:portN call可以执行redis命令 add-node将一个节点添加到集群里第一个参数为新节点的ip:port第二个参数为集群中任意一个已经存在的节点的ip:port del-node移除一个节点 reshard重新分片 check检查集群状态
【4】测试集群
连接任意一个客户端
redis-cli -a redis-pw -c -h 192.168.9.131 -p 8001
参数 ‐a表示服务端密码 ‐c表示集群模式 -h指定ip地址 -p表示端口号
查看集群的信息
cluster info 4.3 节 Redis Cluster 原理
Redis Cluster将所有数据划分为16384个slots(槽位)每个节点负责其中一部分槽位。槽位的信息存储于每个节点中。只有master节点会被分配槽位slave节点不会分配槽位。
槽位定位算法 k1 127001
Cluster 默认会对 key 值使用 crc16 算法进行 hash 得到一个整数值然后用这个整数值对 16384 进行取模来得到具体槽位。
HASH_SLOT CRC16(key) % 16384
命令执行
set k1 v1 存入了12706槽位中
可以通过{}来定义组的概念从而是key中{}内相同内容的键值对放到同一个slot中。
mset k1{test} v1 k2{test} v2 k3{test} v3 让三个key在同一个槽位之中
故障恢复案例
杀死Master节点之后还会重新选举
观察节点信息
cluster nodes 第五章 SpringDataRedis 连接集群 【1】添加依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId
/dependency
【2】编写配置
spring:redis:cluster:nodes: 192.168.9.131:8001,192.168.9.131:8002,192.168.9.132:8001,192.168.9.132:8002,192.168.9.133:8001,192.168.9.133:8002
【3】编写测试
SpringBootTest
class RedisDemo2ApplicationTests {Autowiredprivate RedisTemplate redisTemplate;Testvoid contextLoads() {redisTemplate.opsForValue().set(k6,v6);System.out.println(redisTemplate.opsForValue().get(k6));}
}
第六章 Redis常见问题探析面试题
6.1 节 Redis脑裂问题
6.1.1 什么是集群脑裂
Redis的集群脑裂是指因为网络问题导致Redis Master节点跟Redis slave节点和Sentinel集群处于不同的网络分区此时因为sentinel集群无法感知到master的存在所以将slave节点提升为master节点。 个人理解就是有一个主节点宕机了无法与客户端进行连接就不会参与新的选举在其恢复状态后还是以主节点的身份参与工作造成了多个主节点同时存在的问题这就是脑裂问题。
6.1.2 解决方案
redis.conf配置参数
min-replicas-to-write 1
min-replicas-max-lag 5
参数 第一个参数表示最少的slave节点为1个 第二个参数表示数据复制和同步的延迟不能超过5秒
6.2 节 Redis 缓存预热问题
6.2.1 缓存冷启动
缓存中没有数据由于缓存冷启动一点数据都没有如果直接就对外提供服务了那么并发量上来Mysql就裸奔挂掉了。
6.2.2 冷启动应用场景
新启动的系统没有任何缓存数据在缓存重建数据的过程中系统性能和数据库负载都不太好所以最好是在系统上线之前就把要缓存的热点数据加载到缓存中这种缓存预加载手段就是缓存预热。
6.2.3 解决思路 提前给redis中灌入部分数据再提供服务 如果数据量非常大就不可能将所有数据都写入redis因为数据量太大了第一是因为耗费的时间太长了第二根本redis容纳不下所有的数据 需要根据当天的具体访问情况实时统计出访问频率较高的热数据 然后将访问频率较高的热数据写入redis中肯定是热数据也比较多我们也得多个服务并行读取数据去写并行的分布式的缓存预热
6.3 节 Redis缓存穿透问题
6.3.1 概念
缓存穿透是指缓存和数据库中都没有的数据而用户不断发起请求如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者攻击会导致数据库压力过大。
即用户访问空的数据库与缓存 解释 缓存穿透是指用户查询数据在数据库没有自然在缓存中也不会有。这样就导致用户查询的时候在缓存中找不到每次都要去数据库再查询一遍然后返回空相当于进行了两次无用的查询。这样请求就绕过缓存直接查数据库这也是经常提的缓存命中率问题。 6.3.2 解决方案 对空值缓存如果一个查询返回的数据为空不管数据是否存在我们仍然把这个空结果缓存设置空结果的过期时间会很短最长不超过5分钟。简单的说就是返回一个空值 布隆过滤器如果想判断一个元素是不是在一个集合里一般想到的是将集合中所有元素保存起来然后通过比较确定。
6.3.3 布隆过滤器
布隆过滤器是一种数据结构比较巧妙的概率型数据结构probabilistic data structure特点是高效地插入和查询可以用来告诉你 “某样东西一定不存在或者可能存在”。
所以判断不存在的数据最快 6.3.4 代码实现
【1】引入依赖
dependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.7.17/version
/dependency
【2】java代码实现
// 初始化 注意 构造方法的参数大小10 决定了布隆过滤器BitMap的大小
BitMapBloomFilter filter new BitMapBloomFilter(10);
filter.add(123);
filter.add(abc);
filter.add(ddd);
boolean abc filter.contains(abc);
System.out.println(abc);
6.4 节 Redis 缓存击穿问题
6.4.1 概念
某一个热点 key在缓存过期的一瞬间同时有大量的请求打进来由于此时缓存过期了所以请求最终都会走到数据库造成瞬时数据库请求量大、压力骤增甚至可能打垮数据库。
6.4.2 解决方案 互斥锁在并发的多个请求中只有第一个请求线程能拿到锁并执行数据库查询操作其他的线程拿不到锁就阻塞等着等到第一个线程将数据写入缓存后其他线程直接查询缓存。 热点数据不过期直接将缓存设置为不过期然后由定时任务去异步加载数据更新缓存不咋靠谱
6.4.3 代码实现有待改进
理念是对的但是满足不了的企业的实际需求
真正的解决方案是使用第三方的软件进行控制
public String get(String key) throws InterruptedException {String value jedis.get(key);// 缓存过期if (value null){// 设置3分钟超时防止删除操作失败的时候 下一次缓存不能load db//setnx 如果有值返回0如果没有值设置值返回1Long setnx jedis.setnx(key mutex, 1); jedis.pexpire(key mutex, 3 *60);// 代表设置成功if (setnx 1){// 数据库查询//value db.get(key);//保存缓存jedis.setex(key,3*60,);jedis.del(key mutex);return value;}else {// 这个时候代表同时操作的其他线程已经load db并设置缓存了。需要重新重新获取缓存 //这个睡眠不够严谨不能保证操作完成value的值已经更新完成Thread.sleep(50);// 重试return get(key);}}else {return value;}
}
6.5 节 Redis缓存雪崩问题
6.5.1 概念
缓存雪崩是指在我们设置缓存时采用了相同的过期时间导致缓存在某一时刻同时失效请求全部转发到DBDB瞬时压力过重雪崩。
就是大量的数据同时过期
6.5.2 解决方案
用二级缓存解决先查询本地nginx缓存查询有没有数据有数据直接返回nginx缓存没有数据再去redis分布式缓存查询如果有将redis缓存同步nginx缓存在返回如果redis没有取数据库查询数据库存在将数据同步到redis并返回。只要nginx的过期时间和redis的过期时间不一样就解决了缓存雪崩问题并合理使用了本地缓存和分布式缓存。
6.6 节 Redis 开发规范
6.6.1 key设计技巧 把表名转换为key前缀如 tag: 把第二段放置用于区分key的字段对应msyql中主键的列名如 user_id 第三段放置主键值如 2,3,4 第四段写存储的列名
6.6.2 value设计
拒绝bigkey
防止网卡流量、慢查询string类型控制在10KB以内hash、 list、set、zset元素个数不要超过5000。
6.6.3 命令使用 禁用命令 禁止线上使用keys、flushall、flushdb等通过redis的rename机制禁掉命令或者使用scan的方式渐进式处理。 合理使用select redis的多数据库较弱使用数字进行区分很多客户端支持较差 同时多业务用多数据库实际还是单线程处理会有干扰。 使用批量操作提高效率 原生命令例如mget、mset。 非原生命令可以使用pipeline提高效率 注意但要注意控制一次批量操作的元素个数(例如500以内实际也和元素字节数有关)。 不建议过多使用Redis事务功能 Redis的事务功能较弱(不支持回滚)而且集群版本(自研和官方)要求一次事务操作的key必须在一个slot上。
6.7 节 Redis 数据一致性问题 三种更新策略 先更新数据库再更新缓存 先删除缓存再更新数据库 先更新数据库再删除缓存
先更新数据库再更新缓存
这套方案大家是普遍反对的。为什么呢
线程安全角度 同时有请求A和请求B进行更新操作那么会出现
1线程A更新了数据库
2线程B更新了数据库
3线程B更新了缓存
4线程A更新了缓存
这就出现请求A更新缓存应该比请求B更新缓存早才对但是因为网络等原因B却比A更早更新了缓存。这就导致了脏数据因此不考虑。
先删缓存再更新数据库
该方案会导致不一致的原因是。同时有一个请求A进行更新操作另一个请求B进行查询操作。那么会出现如下情形:
1请求A进行写操作删除缓存
2请求B查询发现缓存不存在
3请求B去数据库查询得到旧值
4请求B将旧值写入缓存
5请求A将新值写入数据库 注意 该数据永远都是脏数据。 先更新数据库再延时删缓存
这种情况存在并发问题吗
1缓存刚好失效
2请求A查询数据库得一个旧值
3请求B将新值写入数据库
4请求B删除缓存
5请求A将查到的旧值写入缓存 发生这种情况的概率又有多少? 发生上述情况有一个先天性条件就是步骤3的写数据库操作比步骤2的读数据库操作耗时更短才有可能使得步骤4先于步骤5。可是大家想想数据库的读操作的速度远快于写操作的因此步骤3耗时比步骤2更短这一情形很难出现。 第七章 总结
【1】简述以下redis事务
答redsi的事务和关系型数据库事务解决问题不一样原则也不一样没有acid原则redis事务保证命令按照队列顺序执行问题所以redis事务分为两个阶段第一个阶段是命令入队第二个阶段是命令执行。
如果队列中命令都证正确那么按照入队顺序执行如果队列中命令语法错误队列所有命名都不执行如果队列命令语法没错但是执行失败只有该命令本身不会执行其他命令都会执行
redis事务命令
multi 开启事务
exec 执行事务
discard 取消事务【2】简述一下Redis的主从复制模式
答Redis集群模式分三种 主从模式 哨兵模式 集群模式
主从模式从一定程度上解决单机Redis的并发问题和可用性问题。但是主从模式问题很大主节点挂了需要手动将从节点切换为主节点所以实际开发很少用到。然后Redis主从复制是哨兵机制和集群机制的根本所以理解主从模式很重要。
主从模式原理如下: 从节点保存主节点master信息。 从节点slave内部通过每秒运行的定时任务维护复制相关逻辑当定时任务发现存在新的主节点后会尝试与该节点建立网络连接。 从节点与主节点建立网络连接 。 发送ping命令 连接建立成功后从节点发送 ping 请求进行首次通信 权限验证如果主节点设置了 requirepass 参数则需要密码验证从节点必须配置 masterauth 参数保证与主节点相同的密码才能通过验证如果验证失败复制将终止从节点重新发起复制流程。 主从复制连接正常通信后对于首次建立复制的场景主节点会把持有的数据全部发送给从节点这部分操作是耗时最长的步骤。 主从刚刚连接的时候进行全量同步全同步结束后进行增量同步。当然如果有需要slave 在任何时候都可以发起全量同步。 redis 策略是无论如何首先会尝试进行增量同步如不成功要求从机进行全量同步。 【3】简述一下哨兵模式
答哨兵模式主要解决主从复制master节点挂掉之后的切换从节点为主节点问题哨兵模式通过监控主从复制主节点和从节点完成自动切换主节点功能。
原理如下 【4】简述以下Redis集群模式
答集群模式至少需要6个redis服务器集群模式就是n个主从复制模式但是需要根据插槽机制分配每个节点存取数据范围。来解决单个主从redis不能存取数据过大问题因为会降低从节点复制速度。
原理 【5】Redis脑裂问题解决
答Redis主从模式下由于主节点挂了从节点新选出主节点由于网络情况挂掉主节点没有降级为从节点导致有两个主节点可以写数据。导致挂掉的主节点的数据无法同步而丢失问题。解决办法
min-replicas-to-write 1
min-replicas-max-lag 5【6】如何解决缓存冷启动问题
答冷启动是指服务器缓存中没有数据直接启动访问量有比较大mysql直接裸机运行。通过缓存预热解决通过storm实时计算出热点数据然后定时将热点数据写入缓存。
【7】如何解决缓存穿透问题
答查询一个redis和mysql肯定都不存在的数据是缓存穿透例如查询id为-1的数据多半为认为恶意攻击。解决方案去数据库查不存在在redis存null,并且设置过期时间5分钟。
或者用布隆过器解决布隆过滤器是一个bitMap数组它说不存在的元素一定不存在他说存在的未必存在。
【8】如何缓存击穿问题
答某一个热点 key在缓存过期的一瞬间同时有大量的请求打进来由于此时缓存过期了所以请求最终都会走到数据库造成瞬时数据库请求量大、压力骤增甚至可能打垮数据库。从造成问题的原因去解决当热点Key失效的一刹那大并发裸奔访问数据库数据库被打垮。我们只需要在热点Key失效的一刹那保证只有一个请求过来就可以了。这种需求肯定用锁解决理论上可以用同步锁解决但这个不靠谱锁只能锁一个进程但是微服务是多个服务是多个进程根本不起作用。所以用分布式锁解决。
【9】如何解决缓存雪崩问题
答大量缓存同时失效数据库被击垮问题。解决思路不让缓存同时失效比如加给缓存过期时间加随机数但是当缓存数据足够大时这个效果不那么明显了可以通过二级缓存技术实现。