页面加载中
博客快捷键
按住 Shift 键查看可用快捷键
ShiftK
开启/关闭快捷键功能
ShiftA
打开/关闭中控台
ShiftD
深色/浅色显示模式
ShiftS
站内搜索
ShiftR
随机访问
ShiftH
返回首页
ShiftL
友链页面
ShiftP
关于本站
ShiftI
原版/本站右键菜单
松开 Shift 键或点击外部区域关闭
互动
最近评论
暂无评论
标签
寻找感兴趣的领域
暂无标签
    0
    文章
    0
    标签
    8
    分类
    10
    评论
    128
    功能
    深色模式
    标签
    JavaScript12TypeScript8React15Next.js6Vue10Node.js7CSS5前端20
    互动
    最近评论
    暂无评论
    标签
    寻找感兴趣的领域
    暂无标签
      0
      文章
      0
      标签
      8
      分类
      10
      评论
      128
      功能
      深色模式
      标签
      JavaScript12TypeScript8React15Next.js6Vue10Node.js7CSS5前端20
      未知歌曲
      未播放
      ♪ 暂无歌词 ♪
      随便逛逛
      博客分类
      文章标签
      复制地址
      深色模式
      AnHeYuAnHeYu
      Search⌘K
      博客
        暂无其他文档

        2024-01-20日

        本文主要介绍了Redis的高可用架构与数据一致性机制,包括哨兵模式的监控、选主流程,以及Cluster分片集群的哈希槽路由原理;同时涵盖了Redis持久化(RDB/AOF)、缓存问题(穿透/击穿/雪崩)及解决方案、分布式锁实现、Java并发工具类、JVM内存结构等面试核心知识点。

        March 23, 202611 分钟 阅读14 次阅读

        有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top

        全网最细面试题手册,支持艾宾浩斯记忆法。这是一份最全面、最详细、最高质量的 java 面试题,不建议你死记硬背,只要每天复习一遍,有个大概印象就行了。 https://store.amazingmemo.com/chapterDetail/1685324709017001`

        会导致数据丢失,分为两种情况

        • 同步过程中服务器挂了
        • 脑裂导致数据丢失

        分片集群是指将 Redis 中数据按照一定的路由分发到不同的节点上。 Redis cluster 是 3.x 版本提供的一种路由方案,是基于 SDK 的。 原理就是,默认是有 16384 个哈希槽,我们可以手动也可以自动的将这些哈希槽分配到所有的节点上,只要全部都分配完即可。 redis 保存数据的时候会在客户端将 key 通过 crc 算法计算出一个值再/16384,然后根据结果去查找对应的节点。

        通过哨兵机制。哨兵其实就是一种特殊的 redis 实例,主要有下面四个功能

        • 监控:监控主节点状态
        • 通知
        • 选主
        • 配置

        。。。。

        大致流程

        1. 哨兵根据配置,当发现主节点超时未上线时,默认认为该主节点客观下线
        2. 当大多数哨兵认为该主节点客观下线的时候,则会开始选主
        3. 哨兵选主主要依据就是谁快谁当主,选主完毕后就会选新主
        4. 选新主主要是根据 offset 位置,runid 位置,等等考虑
        5. 选完新主后就会通知其他节点向新主节点同步数据
        6. 原先的主节点再次上线后,就要丢弃之前的数据,向新主节点同步数据(消息丢失)


        每个 redis 节点保存了所有哈希槽与节点的映射表,并且客户端自己也缓存了一份。

        当集群实例变动后,redis 节点会相互通信自动更新路由表,此时,若客户端此时去访问之前的实例,那么如果此时访问的数据已经同步完成了,就会返回 removed 命令,并包含新的实例地址。此时客户端就拿着新地址去查找数据就行,此时会更新本地缓存。如果此时访问的数据还未完全同步,就会返回 ask 命令,里面包含该客户端请求的数据所在的实例地址,直接访问即可,此时不会更新本地缓存。

        1. 作者认为 redis 集群不会超过 1000 个,够了
        2. 哈希槽过多会影响网络资源

        原理就是通过一层代理管理路由数据,比如 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 个哈希函数处理的结果保存澄数组,通过校验是否匹配,只会告诉你可能包含,不能告诉你不包含。

        1. 初始化 m 个哈希函数
        2. 将值与 m 个哈希函数一一计算,并将结果哈希到数组中
        3. 查询时如果有一个为命中,就是为匹配

        如果客户端发送消息后,该服务器宕机,数据就会丢失。

        超卖:数据丢失未同步就会发生超卖问题

        1. 尽可能避免 redis 发生数据丢失
        2. 避免脑裂的发生
        3. 消息补偿机制
        4. 使用消息队列
        5. 使用分布式事务

        6. 分布式事务

        7. 消息确认机制

        8. 水平扩展服务

        9. 提高消费速度
          1. 非核心功能异步处理
          2. 避免锁操作
          3. 使用线程池提高效率
          4. 本地缓存
        10. 数据库
          1. 优化查询索引
          2. 读写分离
          3. 水平扩展
        11. 消息队列
          1. 水平扩展
          2. 设置优先级
        12. 服务降级,限流,防止服务 GG
        13. 先将这些订单保存到本地,异步处理

        缓存穿透

        1. 布隆过滤器
        2. 缓存结果 缓存失效
        3. 后台同步避免热点索引失效
        4. 限流 缓存雪崩
        5. 随机过期时间
        • 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

        编译完之后就确认了大小,是一个数组,按照初始化顺序保存变量

        • 强引用:手动设置空才会被回收
        • 软引用:内存不够时回收
        • 弱引用:每次都回收
        • 虚引用:随时可能被回收

        垃圾收集算法:

        • 标记-清除
        • 标记-整理
        • 标记-
        最后更新于 March 23, 2026
        On this page
        暂无目录