做课件挣钱的网站,机械网站建设营销,有关优化网站建设的书籍,广州网站建设服务哪家好目录 1 Redis的持久化1.1 RDB持久化方案1.2 AOF持久化方案 2 Redis架构2.1 主从复制架构2.2 哨兵集群设计2.3 哨兵集群设计 3 Redis事务机制4 Redis过期策略与内存淘汰机制4.1 过期策略4.2 内存淘汰机制 5 Redis高频面试题4.1 缓存穿透4.2 缓存击穿4.3 缓存雪崩 1 Redis的持久化… 目录 1 Redis的持久化1.1 RDB持久化方案1.2 AOF持久化方案 2 Redis架构2.1 主从复制架构2.2 哨兵集群设计2.3 哨兵集群设计 3 Redis事务机制4 Redis过期策略与内存淘汰机制4.1 过期策略4.2 内存淘汰机制 5 Redis高频面试题4.1 缓存穿透4.2 缓存击穿4.3 缓存雪崩 1 Redis的持久化 由于 redis 是一个内存数据库所有的数据都是保存在内存当中的内存当中的数据极易丢失所以 redis 的数据持久化就显得尤为重要在redis当中提供了两种数据持久化的方式分别为RDB以及AOF且Redis默认开启的数据持久化方式为RDB方式。
1.1 RDB持久化方案 RDB方案是Redis默认的持久化方案。
按照一定的时间内如果Redis内存中的数据产生了一定次数的更新就将整个Redis内存中的所有数据拍摄一个全量快照文件存储在硬盘上。新的快照会覆盖老的快照文件快照是全量快照包含了内存中所有的内容基本与内存一致。如果Redis故障重启从硬盘的快照文件进行恢复。 RDB快照存储于Redis目录下datas文件夹下dump.rdb 触发条件
手动触发当执行某些命令时会自动拍摄快照【一般不用】 save手动触发拍摄RDB快照的将内存的所有数据拍摄最新的快照 前端运行阻塞所有的客户端请求等待快照拍摄完成后再继续处理客户端请求特点快照与内存是一致的数据不会丢失用户的请求会被阻塞 bgsave手动触发拍摄RDB快照的将内存的所有数据拍摄最新的快照 后台运行主进程会fork一个子进程负责拍摄快照客户端可以正常请求不会被阻塞特点用户请求继续执行用户的新增的更新数据不在快照中 shutdown执行关闭服务端命令flushall清空没有意义 自动触发按照一定的时间内发生的更新的次数拍摄快照 配置文件中有对应的配置决定什么时候做快照
#Redis可以设置多组rdb条件默认设置了三组这三组共同交叉作用满足任何一个都会拍摄快照
save 900 1
save 300 10
save 60 10000为什么默认设置3组如果只有一组策略面向不同的写的场景会导致数据丢失。针对不同读写速度设置不同策略进行交叉保存快照满足各种情况下数据的保存策略。 总结 优点 rdb方式实现的是全量快照快照文件中的数据与内存中的数据是一致的快照是二进制文件生成快照加载快照都比较快体积更小Fork进程实现性能更好总结更快、更小、性能更好 缺点 存在一定概率导致部分数据丢失 应用希望有一个高性能的读写不影响业务允许一部分的数据存在一定概率的丢失【做缓存】大规模的数据备份和恢复。 1.2 AOF持久化方案 RDB存在一定概率的数据丢失如何解决 AOF方案
按照一定的规则将内存数据的操作日志追加写入一个文件中当Redis发生故障重启从文件中进行读取所有的操作日志恢复内存中的数据重新对Redis进行执行用于恢复内存中的数据。 追加的规则
appendfsync always 每更新一条数据就同步将这个更新操作追加到文件中优点数据会相对安全几乎不会出现数据丢失的情况缺点频繁的进行数据的追加增大磁盘的IO导致性能较差 appendfsync everysec常用 每秒将一秒内Redis内存中数据的操作异步追加写入文件优点在安全性和性能之间做了权衡性能要比always高缺点有数据丢失风险 但最多丢失1秒 appendfsync no 交给操作系统来做不由Redis控制肯定不用的 总结 优点安全性和性能做了折中方案提供了灵活的机制如果性能要求不高安全性可以达到最高缺点 这个文件是普通文本文件相比于二进制文件来说每次追加和加载比较慢数据的变化以追加的方式写入AOF文件 问题文件会不断变大文件中会包含不必要的操作【过期的数据】解决模拟类似于RDB做全量的方式定期生成一次全量的AOF文件 应用数据持久化安全方案理论上绝对性保证数据的安全 持久化方案两种方案怎么选
两种方案都可以用默认不配置AOF使用的RDB问题两种都用重启Redis加载的是谁的数据 加载AOF
2 Redis架构 Redis的服务只有单台机器问题1单点故障问题如果Redis服务故障整个Redis服务将不可用 单点故障问题 问题2单台机器的内存比较小数据存储的容量不足会导致redis无法满足需求 单机资源不足问题 解决方案分布式 2.1 主从复制架构 分布式主从架构
Master主节点 负责对外提供数据的读写 Slave从节点 负责对外提供读的请求负责与主节点同步数据
特点主从节点上的数据都是一致的连接任何一个节点实现读默认写操作只能连接主节点
优缺点
优点实现了读写分离分摊了读写的压力负载如果一台Redis的Slave故障其他的Redis服务节点照常对外提供服务 解决了Redis单点故障问题 缺点如果Master故障整个集群不能对外提供写的操作Master没有HA机制 带来了Master单点故障问题
2.2 哨兵集群设计 主从复制集群的Master存在单点故障问题怎么解决 类似于ZK的设计 每台节点存储的数据都是一样的如果Leader故障允许Follower选举成为Leader 哨兵设计 思想基于主从复制模式之上封装了哨兵模式如果Master出现故障让Slave选举成为新的Master 实现哨兵进程 实现 必须能发现Master的故障必须负责重新选举新的Master Redis主从架构
哨兵进程 每个哨兵负责监听所有Redis节点和其他哨兵为什么要监听所有Redis的节点发现所有节点是否会出现故障 如果Master出现故障会进行投票选择一个Slave来成为新的Master 为什么要监听别的哨兵如果哨兵故障不能让这个哨兵参与投票选举等
哨兵功能
集群监控监控节点状态消息通知汇报节点状态故障转移实现Master重新选举配置中心实现配置同步
流程
step1如果Master突然故障有一个哨兵会发现这个问题这个哨兵会立即通告给所有哨兵 主观性故障【sdown】 step2当有一定的个数的哨兵都通告Master故障了整体认为Master故障了 客观性故障【odown】 step3所有哨兵根据每台Slave通信的健康状况以及Slave权重选举一个新的Masterstep4将其他所有的Slave的配置文件中的Master切换为当前最新的Master
2.3 哨兵集群设计 Redis哨兵集群中的存储容量只有单台机器如何解决大量数据使用Redis存储问题 分片集群模式解决了单点故障和单机资源不足的问题。
将多个Redis小集群从逻辑上合并为一个大集群每个小集群分摊一部分槽位对每一条Redis的数据进行槽位计算这条数据属于哪个槽位就存储对应槽位的小集群中
分片的规则根据Key进行槽位运算CRC16【K】 16383 0 ~ 16383 3 Redis事务机制 事务定义事务是数据库操作的最小工作单元包含原子性、一致性、隔离性、持久性
Redis事务Redis一般不用事务 Redis本身是单线程的所以本身没有事务等概念 Redis 支持事务的本质是一组命令的集合事务支持一次执行多个命令串行执行每个命令。将一组需要一起执行的命令放在multi和exec之间。 一旦Redis开启了事务将所有命令放入一个队列中提交事务时对整个队列中的命令进行执行 redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令 没有隔离性批量的事务命令执行前在缓存队列中没有事务交叉不存在脏读幻读等问题 不能保证原子性单条命令是原子性执行的但事务不保证原子性且没有回滚机制事务中任意命令执行失败其余的命令仍会被执行。 过程 开启事务提交命令执行事务 命令 multi开启事务exec执行事务discard取消事务
测试 正常使用 set user1 hadoop1
set user2 hadoop2
get user1
get user2
multi
set user1 hadoop3
set user2 hadoop4
exec
get user1
get user2都执行 语法【编译】错误 flushdb
set user1 hadoop1
set user2 hadoop2
get user1
get user2
multi
set user1 hadoop3
sets user2 hadoop4
exec
get user1
get user2都不执行 类型【运行】错误 flushdb
set user1 hadoop1
set user2 hadoop2
get user1
get user2
multi
set user1 hadoop3
lpush user2 hadoop4 # 运行错误
exec
get user1
get user2user1执行user2不执行 取消事务 flushdb
set user1 hadoop1
set user2 hadoop2
get user1
get user2
multi
set user1 hadoop3
set user2 hadoop4
discard
get user1
get user2都不执行 总结 Redis 的事务机制很弱在事务回滚机制上只能对基本的语法错误进行判断。事务是Redis实现在服务端的行为用户执行multi命令时服务器会将对应这个用户的客户端对象设置为一个特殊的状态在这个状态下后续用户执行的命令不会被真的执行而是被服务器缓存起来直到用户执行exec命令为止服务器会将这个用户对应的客户端对象中缓存的命令按照提交的顺序依次执行。 4 Redis过期策略与内存淘汰机制 Redis使用的是内存内存如果满了怎么解决 4.1 过期策略 设计思想避免内存满指定Key的存活时间到达存活时间以后自动删除。命令expire/setex
定时过期指定Key的存活时间一直监听这个存活时间一旦达到存活时间自动删除 需要CPU一直做监听如果Key比较多CPU的消耗比较严重 惰性过期指定Key的存活时间当使用这个Key的时候判断是否过期如果过期就删除 如果某个Key设置了过期时间但是一直没有使用不会被发现过期了就会导致资源浪费 定期过期每隔一段时间就检查数据是否过期如果过期就进行删除 中和的策略机制
Redis中使用了惰性过期和定期过期两种策略共同作用
4.2 内存淘汰机制 设计思想内存满了怎么淘汰
Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时怎么处理需要新写入且需要申请额外空间的数据 Redis 源码中的默认配置
实际项目中设置内存淘汰策略maxmemory-policy allkeys-lru移除最近最少使用的key。
缓存使用allkeys-lru数据库使用volatile-lru / noeviction
5 Redis高频面试题 在应用程序和MySQL数据库中建立一个中间层Redis缓存通过Redis缓存可以有效减少查询数据库的时间消耗但是引入redis又有可能出现缓存穿透、缓存击穿、缓存雪崩等问题。 4.1 缓存穿透 缓存穿透key对应的数据在数据源并不存在每次针对此key的请求从缓存获取不到请求都会到数据源从而可能压垮数据源。
总的来说查询Key缓存和数据源都没有频繁查询数据源。比如用一个不存在的用户 id 获取用户信息无论论缓存还是数据库都没有若黑客利用此漏洞进行攻击可能压垮数据库。
解决缓存穿透的方案主要有两种
当查询不存在时也将结果保存在缓存中。但是这可能会存在一种问题大量没有查询结果的请求保存在缓存中这时我们就可以将这些请求的key设置得更短一些提前过滤掉不合法的请求可以使用Redis中布隆过滤器
布隆过滤器可能存在误判意思就是某个数据可能不存在但是可能误判为存在。 4.2 缓存击穿 缓存击穿key对应的数据库存在但在redis中过期此时若有大量并发请求过来这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存这个时候大并发的请求可能会瞬间把后端DB压垮。
总的来说查询Key缓存过期大量并发频繁查询数据源。
业界比较常用的做法使用互斥锁。简单地来说就是在缓存失效的时候判断拿出来的值为空不是立即去load db查询数据库而是先使用缓存工具的某些带成功操作返回值的操作比如Redis的SETNX或者Memcache的ADD去set一个mutex key就是只让一个线程构建缓存其他线程等待构建缓存的线程执行完重新从缓存获取数据。 在请求数据库这一步进行上锁这个时候只有一个线程可以抢到这个锁这个线程查询到数据库再重新将数据写入缓存其他线程再去缓存中查询。 4.3 缓存雪崩 缓存雪崩当缓存服务器重启或者大量缓存集中在某一个时间段失效这样在失效的时候也会给后端系统(比如DB)带来很大压力。
总的来说缓存不可用服务器重启或缓存失效频繁查询数据源。
与缓存击穿的区别在于这里针对很多key缓存前者则是某一个key。缓存正常从Redis中获取示意图如下 缓存失效瞬间示意图如下 缓存失效时的雪崩效应对底层系统的冲击非常可怕大多数系统设计者考虑用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写从而避免失效时大量的并发请求落到底层存储系统上。还有一个简单方案就时将缓存失效时间分散开比如可以在原有的失效时间基础上增加一个随机值比如1-5分钟随机这样每一个缓存的过期时间的重复率就会降低就很难引发集体失效的事件。