写在后面
📌Xmind 文件获取:GitHub 继续更新中,别忘了 star 喔~
「Java 学习 + 面试指南」思维导图,计算机自学指南,包含 Java 根底、JVM、数据库、mysql、redis、计算机网络、算法、数据结构、操作系统等,后盾技术栈 / 架构师之路 / 全栈开发社区,阿里,腾讯,百度,美团,头条等春招 / 秋招 / 校招 / 面试
思维导图(png 格局可下载放大)
Redis
优缺点
长处
- 读写性能优异
- 反对数据长久化
- 反对事务,所有操作都是原子性的,反对对几个操作合并后的原子性执行。
- 数据结构丰盛
- 主从复制, 进行读写拆散
毛病
- 较小数据量的高性能操作和运算
-
不具备主动容错和复原性能
- 须要期待机器重启或者手动切换前端的 IP 能力复原
-
主机宕机,宕机前有局部数据未能及时同步到从机
- 升高了零碎的可用性
- 较难反对在线扩容
不必 map/guava
-
本地缓存
- 生命周期随着 jvm 的销毁而完结
- 每个实例都须要各自保留一份缓存,缓存不具备一致性
快的起因
-
齐全基于内存
- 查找和操作的工夫复杂度都是 O(1)
- 数据结构简略
-
单线程
- 防止了不必要的上下文切换和竞争条件,也不存在多过程或者多线程导致的切换而耗费 CPU,不必去思考各种锁的问题,不存在加锁开释锁操作,没有因为可能呈现死锁而导致的性能耗费
- 多路 I/O 复用模型,非阻塞 IO
memcached
- (1) memcached 所有的值均是简略的字符串,redis 作为其替代者,反对更为丰盛的数据类型
- (2) redis 的速度比 memcached 快很多
- (3) redis 能够长久化其数据
- 都反对分布式
根底
数据类型
- STRING
- LIST
- SET
- HASH
-
ZSET
-
jumplist
- 多层链表 + 二分法
-
利用场景
- 计数器
- 缓存
-
会话缓存
- 对立存储多台应用服务器的会话信息
-
查找表
- DNS 记录
-
音讯队列(公布 / 订阅性能)
- List 是一个双向链表,能够通过 lpush 和 rpop 写入和读取音讯
-
分布式锁
-
SETNX
- 随机 value,比拟雷同才删除解锁
-
长久化
-
RDB(默认)快照
- dump.rdb
- fork 子过程来实现写操作,让主过程持续解决命令,所以是 IO 最大化
- 比 AOF 的启动效率更高
-
AOF
- 将 Redis 执行的每次写命令记录到独自的日志文件中
- 会优先选择 AOF 复原
- 每进行一次 命令操作就记录到 aof 文件中一次
- AOF 文件比 RDB 文件大,且复原速度慢
- rdb 启动效率低
- AOF 文件比 RDB 更新频率高,优先应用 AOF 还原数据
过期键的删除策略
- 用于解决过期的缓存数据
-
定时过期
- 占用大量的 CPU 资源
-
惰性过期 用
- 当拜访一个 key
-
定期过期 用
- 扫描肯定数量的数据库的 expires 字典中肯定数量的 key
- 过期工夫和永恒无效 EXPIRE 和 PERSIST
内存淘汰策略
- allkeys-lru
- 用于解决内存不足时的须要申请额定空间的数据
线程模型
-
文件事件处理器
- 多个套接字、IO 多路复用程序、文件事件分派器(单线程)、事件处理器
- 应用 I/O 多路复用(multiplexing)程序来同时监听多个套接字
依据套接字目前执行的工作来为套接字关联不同的事件处理器
事务
- 要么全副被执行,要么全副都不执行
-
MULTI、EXEC、DISCARD、WATCH 等一组命令的汇合, 一个事务中所有命令都会被序列化
-
WATCH
- 为 Redis 事务提供 check-and-set(CAS)行为。能够监控一个或多个键,一旦其中有一个键被批改(或删除),之后的事务就不会执行,监控始终继续到 EXEC 命令。
-
DISCARD
- 客户端能够清空事务队列,并放弃执行事务
-
-
三个阶段
-
事务开始 MULTI
- 命令不会立刻被执行,而是被放到一个队列中
- 命令入队
-
事务执行 EXEC
- 执行所有事务块内的命令
-
-
不反对回滚
- 在事务失败时不进行回滚,而是继续执行余下的命令
-
隔离性
- 单过程程序,并且它保障在执行事务时,不会对事务进行中断
-
不反对原子性
- 不保障原子性,且没有回滚
异步队列
- 应用 list 类型保留数据信息,rpush 生产音讯,lpop 生产音讯,当 lpop 没有音讯时,能够 sleep 一段时间,而后再查看有没有信息,
如果不想 sleep 的话,能够应用 blpop, 在没有信息的时候,会始终阻塞,直到信息的到来。 - redis 能够通过 pub/sub 主题订阅模式实现一个生产者,多个消费者,当然也存在肯定的毛病,当消费者下线时,生产的音讯会失落。
集群计划
哨兵模式
- 集群监控:负责监控 redis master 和 slave
- 音讯告诉:如果某个 redis 实例有故障,告诉给管理员。
-
故障转移:如果 master node 挂掉了,会主动转移到 slave node 上。
- 判断一个 master node 是否宕机了,大部分的哨兵都批准,分布式选举
- 配置核心:故障转移,告诉 client 客户端新的 master 地址。
-
外围常识
- 至多须要 3 个实例
- 哨兵 + redis 主从的部署架构,是不保证数据零失落的,只能保障高可用性。
Cluster 计划(服务端路由查问)
-
分布式寻址算法
- hash 算法(大量缓存重建)
- 一致性 hash 算法(主动缓存迁徙)+ 虚构节点(主动负载平衡解决数据歪斜问题)
- redis cluster 的 hash slot 哈希槽 算法 16384
-
主从架构
- 每份数据分片会存储在多个互为主从的多节点
- 多个节点间的数据不放弃一致性
- 先写主节点,再同步到从节点(反对配置为阻塞同步)
- 当客户端操作的 key 没有调配在该节点上时,redis 会返回转向指令,指向正确的节点
- 扩容时时须要须要把旧节点的数据迁徙一部分到新节点
-
长处
- 反对动静扩容
- 具备 Sentinel 的监控和主动 Failover(故障转移)能力
- 免去了 proxy 代理的损耗
- 连贯集群中任何一个可用节点
基于客户端调配
- 采纳哈希算法将 Redis 数据的 key 进行散列,通过 hash 函数,特定的 key 会映射到特定的 Redis 节点上
- Redis 实例彼此独立,互相无关联
- 不反对动静增删节点,每个客户端都须要更新调整
- 连贯不能共享,当利用规模增大时,资源节约制约优化
基于代理服务器分片
- 申请到一个代理组件,代理解析客户端的数据,并将申请转发至正确的节点
- 切换成本低
- 代理层多了一次转发,性能有所损耗
主从架构
- 一主多从,主负责写,并且将数据复制到其它的 slave 节点,从节点负责读。所有的读申请全副走从节点。撑持读高并发。
- redis replication -> 主从架构 -> 读写拆散 -> 程度扩容撑持读高并发
-
外围机制
-
异步形式复制
- 发送一个 PSYNC
- full resynchronization 全量复制,master 会启动一个后盾线程,开始生成一份 RDB 快照文件
- 将这个 RDB 发送给 slave,slave 会先写入本地磁盘,而后再从本地磁盘加载到内存中
- master 会将内存中缓存的写命令发送到 slave
-
-
必须开启 master node 的长久化
- 在 master 宕机重启的时候数据是空的,而后可能一通过复制,slave node 的数据也丢了
-
从备份中筛选一份 rdb 去复原 master,这样能力确保启动的时候,是有数据的
- lave node 能够主动接管 master node,但也可能 sentinel 还没检测到 master failure,master node 就主动重启了,还是可能导致下面所有的 slave node 数据被清空
分区毛病
-
波及多个 key 的操作通常不会被反对
-
不能对两个汇合求交加
- 被存储到不同的 Redis 实例
-
- 同时操作多个 key, 则不能应用 Redis 事务.
-
数据处理会非常复杂
- 必须从不同的 Redis 实例和主机同时收集 RDB / AOF 文件
-
动静扩容或缩容可能十分复
- Redis 集群在运行时减少或者删除 Redis 节点,能做到最大水平对用户通明地数据再均衡,但其余一些客户端分区或者代理分区办法则不反对这种个性。
分布式锁
-
SETNX SET if Not eXists
- 当且仅当 key 不存在,将 key 的值设为 value。给定的 key 曾经存在,则 SETNX 不做任何动作
解决 Redis 的并发竞争 Key
-
分布式锁(zookeeper 和 redis 都能够实现分布式锁)
- 每个客户端对某个办法加锁时,在 zookeeper 上的与该办法对应的指定节点的目录下,生成一个惟一的刹时有序节点。
判断是否获取锁的形式很简略,只须要判断有序节点中序号最小的一个。当开释锁的时候,只需将这个刹时节点删除即可。
同时,其能够防止服务宕机导致的锁无奈开释,而产生的死锁问题。实现业务流程后,删除对应的子节点开释锁。 -
Redlock
- 互斥拜访,即永远只有一个 client 能拿到锁
- 最终 client 都可能拿到锁,不会呈现死锁的状况
- 只有大部分 Redis 节点存活就能够失常提供服务
- 每个客户端对某个办法加锁时,在 zookeeper 上的与该办法对应的指定节点的目录下,生成一个惟一的刹时有序节点。
缓存异样
缓存雪崩
-
缓存同一时间大面积的生效
- 过期工夫设置随机,避免同一时间大量数据过期景象产生
- 加锁排队
缓存穿透
-
缓存和数据库中都没有的数据
- 接口层减少校验,id<= 0 的间接拦挡
- 将 key-value 对写为 key-null,缓存无效工夫能够设置短点,如 30 秒。避免重复用同一个 id 暴力攻打
-
布隆过滤器判断在不在数据库
-
哈希表,屡次 hash
- 有肯定的误识别率和删除艰难
- 所有的 Hash 函数通知咱们该元素在汇合中,能力确定在汇合中
-
缓存击穿
-
热点数据缓存工夫到期
- 设置热点数据永远不过期
- 加互斥锁
缓存预热
- 将相干的缓存数据间接加载到缓存零碎
缓存降级
-
依据一些要害数据进行主动降级,也能够配置开关实现人工降级
- Redis 呈现问题,不去数据库查问,而是间接返回默认值给用户
数据库双写时的数据一致性
-
先更新数据库,而后再删除缓存
-
一致性:缓存删除失败,数据不统一
- 高并发下:A 去查忽然生效查脏数据,B 更新数据库,B 写入缓存,A 写入缓存 -> 数据不统一
-
-
先删除缓存,而后再更新数据库
- 高并发下:A 删除,B 读数据库脏数据,B 写入,A 更新数据库 -> 数据不统一
-
不更新缓存
- 有大量冷数据占用资源,用到缓存才去算缓存