2024-01-20
2024-01-20
程序员朱永胜有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步, 认准
https://blog.zysicyj.top
全网最细面试题手册,支持艾宾浩斯记忆法。这是一份最全面、最详细、最高质量的 java 面试题,不建议你死记硬背,只要每天复习一遍,有个大概印象就行了。https://store.amazingmemo.com/chapterDetail/1685324709017001`
会导致数据丢失,分为两种情况
- 同步过程中服务器挂了
- 脑裂导致数据丢失
分片集群是指将 Redis 中数据按照一定的路由分发到不同的节点上。
Redis cluster 是 3.x 版本提供的一种路由方案,是基于 SDK 的。
原理就是,默认是有 16384 个哈希槽,我们可以手动也可以自动的将这些哈希槽分配到所有的节点上,只要全部都分配完即可。
redis 保存数据的时候会在客户端将 key 通过 crc 算法计算出一个值再 /16384,然后根据结果去查找对应的节点。
通过哨兵机制。哨兵其实就是一种特殊的 redis 实例,主要有下面四个功能
- 监控:监控主节点状态
- 通知
- 选主
- 配置
。。。。
大致流程
- 哨兵根据配置,当发现主节点超时未上线时,默认认为该主节点客观下线
- 当大多数哨兵认为该主节点客观下线的时候,则会开始选主
- 哨兵选主主要依据就是谁快谁当主,选主完毕后就会选新主
- 选新主主要是根据 offset 位置,runid 位置,等等考虑
- 选完新主后就会通知其他节点向新主节点同步数据
- 原先的主节点再次上线后,就要丢弃之前的数据,向新主节点同步数据(消息丢失)
每个 redis 节点保存了所有哈希槽与节点的映射表,并且客户端自己也缓存了一份。
当集群实例变动后,redis 节点会相互通信自动更新路由表,此时,若客户端此时去访问之前的实例,那么如果此时访问的数据已经同步完成了,就会返回 removed 命令,并包含新的实例地址。此时客户端就拿着新地址去查找数据就行,此时会更新本地缓存。如果此时访问的数据还未完全同步,就会返回 ask 命令,里面包含该客户端请求的数据所在的实例地址,直接访问即可,此时不会更新本地缓存。
- 作者认为 redis 集群不会超过 1000 个,够了
- 哈希槽过多会影响网络资源
原理就是通过一层代理管理路由数据,比如 codis,就是通过 codis server 和 codis proxy 管理。客户端请求发送到代理上,代理再根据路由信息转发到具体的实例上。
实例将数据发送到新节点,此时数据只读,当数据更新完,删掉本地数据
rdb:快照,redis fork 子线程拷贝快照
aof:命令备份,保存执行的命令,后台会定期合并命令减少文件大小
混合使用最佳,配置 rdb 为 5 秒,aof,这样恢复先恢复 rdb 再恢复 5 秒内的 aof
字符串:最大 512M
列表:
数组:
有序数组:
哈希:
bitmap:二进制
hyperlog:
geo:经纬度
分布式锁:set nx 老的版本是 set if not exist + expire 新版本是 set key value nx px 1000
缓存穿透:值得是没命中缓存,直接打到数据库。缓存未命中的数据,布隆过滤器
缓存击穿:缓存失效瞬间大量请求打到数据库。布隆过滤器,加锁,热点数据一直加锁
缓存雪崩:大量缓存同时失效,设置随机过期时间,消费降级
- hashmap
- guava cache
- kfcache
- jcache
- spring cache
基于内存,高效的数据结构,非阻塞 IO
redo log 是为了实现事务,undo log 是为了保证事务
- 基于内存
- 高效的数据结构
- 无锁
- 异步 IO 模型
- 事件驱动机制
- 支持批量执行
redo log 保证事务的持久性
undo log 保证事务的一致性和原子性
底层原理是通过 n 个哈希函数处理的结果保存澄数组,通过校验是否匹配,只会告诉你可能包含,不能告诉你不包含。
- 初始化 m 个哈希函数
- 将值与 m 个哈希函数一一计算,并将结果哈希到数组中
- 查询时如果有一个为命中,就是为匹配
如果客户端发送消息后,该服务器宕机,数据就会丢失。
超卖:数据丢失未同步就会发生超卖问题
- 尽可能避免 redis 发生数据丢失
- 避免脑裂的发生
- 消息补偿机制
- 使用消息队列
- 使用分布式事务
- 分布式事务
- 消息确认机制
- 水平扩展服务
- 提高消费速度
- 非核心功能异步处理
- 避免锁操作
- 使用线程池提高效率
- 本地缓存
- 数据库
- 优化查询索引
- 读写分离
- 水平扩展
- 消息队列
- 水平扩展
- 设置优先级
- 服务降级,限流,防止服务 GG
- 先将这些订单保存到本地,异步处理
缓存穿透
- 布隆过滤器
- 缓存结果
缓存失效 - 后台同步避免热点索引失效
- 限流
缓存雪崩 - 随机过期时间
- linkedlistblokingqueue:FIFO
- Arraylistblockingqueue:数组
- linkedlobkingqueue:无界阻塞队列
- arrayblockingqueue:FIFO
- 优先级队列
- delayqueue:延迟队列
bitmap:以日期维度保存,bitcount
hyperlog:以日期维度保存,pfcount:不精确
- fixedthreadpool
- cachedthreadpool
- singledthreadpool
- schedualthreadpool
- singlescheduthreadpool
- 无锁
- 偏向锁
- CAS
- 同步锁
AOT:编译时处理热点数据
JIT:运行时处理热点数据
基于 IEEExxx 标准,无法精确表示浮点数
堆 - 栈
共同:都不能被实例化
接口:可以定义常量,静态方法,接口不能写实现
抽象类:只能被继承,啥都可以
string:基础类型
stringbuffer:线程不安全,内部通过 append 拼接
stringbuild:可变,线程安全,加锁
- 基本属性(魔术、版本号等等)
- 常量池
- 方法名
- 变量名
- 属性名(字节码相关信息)
乐观锁:发生争抢时上锁(写上锁)
悲观锁:直接上锁(读写都上锁)
- 原子数组
- Unsafe
- Lock
- concurrentHashMap
- CopyOnWriteList
- ReetranLock
- Countdownlatch
- Samplare
- 常量池
- 栈
- 线程计数器
- 操作数栈
- 局部变量表
- 本地方法表
- 方法引用
- 堆
- 方法区
直接内存不受垃圾回收器管理,大小没有上线,也避免拷贝,性能高高高
- aborting
- callerruns
- discarding
- discardingoldest
- 更易读
- 性能低
- 易同步
- 更不安全
- 兼容高
类、方法、属性、接口
适配器就是将现有的功能兼容目标接口
异步 IO:通过操作系统的事件回调机制实现消息回调,提高 IO 读取速度
热部署、tomcat 多应用部署、jdbc 加载驱动、arthas 等等
clint 保证初始化顺序
局部变量表
本地方法表
返回类型
记录下个指令地址,不会发生 OOM
编译完之后就确认了大小,是一个数组,按照初始化顺序保存变量
- 强引用:手动设置空才会被回收
- 软引用:内存不够时回收
- 弱引用:每次都回收
- 虚引用:随时可能被回收
垃圾收集算法:
- 标记 - 清除
- 标记 - 整理
- 标记 -