小菜鸟

java菜鸟号正在起航

Redis 主从复制详解(基于 6.0.10 版本)

Redis 主从复制(Master-Slave Replication)是实现高可用和读写分离的核心机制,通过将主节点(Master)的数据同步到从节点(Slave),避免单点故障并分担读压力。本文详细解析主从复制的原理、配置方式、常见模式及哨兵(Sentinel)自动故障转移机制。

主从复制核心原理

主从复制通过 PSYNC 命令 实现数据同步,支持全量同步和部分同步两种模式,兼顾初次复制和断线重连场景。

PSYNC 命令的两种模式

  • 全量同步(Full Resync):适用于初次复制(Slave 首次连接 Master)。
    流程:
    1. Slave 向 Master 发送 PSYNC ? -1(表示需要全量同步)。
    2. Master 生成 RDB 快照,发送给 Slave;同时缓存快照生成期间的写命令(复制积压缓冲区)。
    3. Slave 加载 RDB 快照,再执行缓存的写命令,最终与 Master 数据一致。
  • 部分同步(Partial Resync):适用于断线重连(Slave 短暂断开后重新连接)。
    流程:
    1. Slave 重连后,向 Master 发送 PSYNC <master_runid> <offset>(携带上次同步的 Master 标识和偏移量)。
    2. Master 验证master_runid(自身标识)和offset(同步偏移量):
      • 若有效(偏移量在复制积压缓冲区内),仅发送偏移量后的增量写命令。
      • 若无效(如 Master 重启或偏移量过期),触发全量同步。

核心概念

  • master_runid:Master 的唯一标识(每次重启会变化),用于 Slave 验证连接的是否为同一 Master。
  • 复制偏移量(Offset):Master 和 Slave 分别维护的计数器,记录已同步的字节数(确保数据一致性)。
  • 复制积压缓冲区:Master 端的环形缓冲区(默认 1MB),存储最近的写命令,用于部分同步。可通过 repl-backlog-size 调整大小(如 repl-backlog-size 10mb)。

主从复制配置

主从复制采用 “配从不配主” 原则:只需配置 Slave 指向 Master,Master 无需额外配置。

阅读全文 »

Redis 过期删除与内存淘汰机制详解(基于 6.0.10 版本)

Redis 允许为键设置过期时间,但如何高效处理过期键、避免内存溢出,是其性能优化的核心问题。不同于简单的定时删除,Redis 采用定期删除 + 惰性删除的混合策略处理过期键,并在内存不足时通过淘汰机制释放空间。本文详细解析这两种机制的原理、配置及实践建议。

过期键的删除策略

Redis 未采用 “每个过期键对应一个定时器” 的定时删除策略(避免 CPU 资源耗尽),而是结合定期删除惰性删除,在内存占用与 CPU 消耗之间取得平衡。

1. 惰性删除(Lazy Eviction)

  • 核心逻辑:键过期后不主动删除,仅在被访问时(如 gethget 等命令)才检查是否过期。若过期,则删除该键并返回空;若未过期,则正常返回值。
  • 优势:无需额外 CPU 资源监控过期键,仅在必要时执行删除,适合低频访问的过期键。
  • 劣势:若过期键长期未被访问,会占用内存(“内存泄漏” 风险),需配合定期删除弥补。

2. 定期删除(Periodic Eviction)

  • 核心逻辑:Redis 每隔一段时间(由hz配置控制,默认每秒 10 次)主动扫描部分过期键并删除,具体步骤:
    1. 从 “过期键字典”(专门存储设置了过期时间的键)中随机抽取 20 个键
    2. 删除这 20 个键中已过期的键。
    3. 若过期键占比超过 25%,重复步骤 1(继续抽取删除),直至占比低于 25% 或达到最大扫描时间(默认 25ms)。
  • 配置参数:
    • hz <num>:控制定期扫描的频率(默认 10,即每秒 10 次)。值越大,扫描越频繁,过期键删除越及时,但 CPU 消耗越高。
  • 优势:主动清理长期未访问的过期键,减少内存浪费。
  • 注意:为避免扫描耗时过长阻塞服务,单次扫描时间被限制在 25ms 内,因此无法保证所有过期键都被及时删除。

3. 主从结构中的过期键处理

在主从复制中,过期键的删除存在特殊逻辑:

  • 主服务器:采用上述 “定期 + 惰性” 策略正常删除过期键,并向从服务器发送 del 命令。
  • 从服务器:即使键已过期,也不主动删除,仅在收到主服务器的 del 命令后才删除。
  • 潜在问题:主从同步存在延迟时,从服务器可能返回已过期的键(主服务器已删除,但 del 命令未同步),导致短暂的数据不一致。

内存淘汰机制(Maxmemory Policy)

当 Redis 内存使用达到 maxmemory 配置的阈值时,会触发内存淘汰机制,主动删除部分键以释放空间。淘汰机制的核心是 “按规则筛选并删除键”,具体规则由 maxmemory-policy 配置。

阅读全文 »

Hadoop 性能调优:从操作系统到组件参数,一步一步来

Hadoop 集群跑得慢,原因可能出在任何一层——操作系统限制、JVM 参数、HDFS 配置、MapReduce 参数。盲目调参不如系统性地排查。

调优的原则是:先调操作系统,再调 Hadoop 参数。 底层不稳,上层再怎么调也是白搭。

操作系统层:必做项

这部分配置是 Hadoop 跑得稳的基础,不管什么场景都建议做。

1. 增大文件打开限制

Hadoop 在运行时会打开大量文件——HDFS 的数据块文件、MapReduce 的中间结果、日志文件。默认的 1024 不够用,会报 too many open files

# /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535

改完重启或重新登录生效,用 ulimit -n 确认。

2. 关闭 swap 分区

Hadoop 对内存延迟敏感,swap 是磁盘 IO,比内存慢 10 万倍。一旦内存不够开始 swap,NameNode 或者 ResourceManager 的响应时间会急剧增加,整个集群跟着抖。

# /etc/sysctl.conf
vm.swappiness = 0

改完执行 sysctl -p 生效。如果服务器内存本身就小(比如 < 16GB),优先加内存,别指望 swap 兜底。

3. 调整网络连接队列

集群节点之间通信频繁,TCP 连接队列默认太小会丢包、重传,影响 Shuffle 性能。

# /etc/sysctl.conf
net.core.somaxconn = 65535  # 最大TCP连接队列长度,默认128
net.ipv4.tcp_max_syn_backlog = 65535  # SYN队列长度,默认1024

改完 sysctl -p 生效。

4. 设置磁盘预读缓冲区

Hadoop 处理大文件是顺序读,预读缓冲区提前把数据从磁盘读到内存,减少寻道时间。默认 128KB 偏小,大文件场景建议调到 2MB 或更大。

# 查看当前值(单位是 512 字节扇区)
blockdev --getra /dev/sda

# 设置为 2MB(4096 × 512 = 2MB)
blockdev --setra 4096 /dev/sda
阅读全文 »

Redis 持久化机制详解:RDB、AOF 与混合模式

Redis 作为内存数据库,数据默认存储在内存中,若发生宕机可能导致数据丢失。持久化机制通过将内存数据写入磁盘,确保数据可恢复。Redis 提供两种核心持久化方式:RDB(快照)AOF(Append Only File),4.0 版本后新增 混合模式,结合两者优势。本文基于 Redis 6.0.10 版本,详细解析这三种机制的原理、配置与优缺点。

RDB 持久化(Redis DataBase)

RDB 是 Redis 默认的持久化方式,通过定时生成内存数据的快照(二进制文件)实现持久化,恢复时通过加载快照文件还原数据。

核心原理

  • 快照生成:在指定时间间隔内,当写入操作满足触发条件时,Redis 会 fork 一个子进程,将内存数据完整写入临时文件,完成后替换旧快照文件(dump.rdb)。

  • Copy On Write(COW)fork 后父子进程共享内存数据,父进程处理新请求时,若修改数据会复制对应内存页(不影响子进程的快照生成),避免数据不一致。

    子进程在做数据持久化的过程中,只会进行遍历读取,但是父进程必须服务客户端请求,可能会对数据进行修改,此时使用COW(copy on write)机制,当父进程写数据时,将该内存页复制一份父进程来操作修改,其余的还是在共享内存内。随着父进程持续的修改数据,越来越多的共享页面被分离出来,内存会持续增长,但是最多也不会超过原有数据内存的2倍

    每一页是4K

配置参数(redis.conf)

RDB 配置位于 SNAPSHOTTING 模块,核心参数如下:

参数 作用 默认值
save <seconds> <changes> 触发快照的条件(多少秒内发生多少次修改),多条件为 “或” 关系。 save 900 1(15 分钟 1 次)、save 300 10(5 分钟 10 次)、save 60 10000(1 分钟 10000 次)
stop-writes-on-bgsave-error 若快照生成失败,是否停止写入操作(避免数据不一致)。 yes
rdbcompression 是否使用 LZF 算法压缩快照文件(节省空间,略增 CPU 开销)。 yes
rdbchecksum 是否对快照文件进行 CRC64 校验(确保完整性,略增性能损耗)。 yes
dbfilename 快照文件名称。 dump.rdb
dir 快照文件存储目录。 /usr/local/var/db/redis/

save 900 1 #15分钟内修改了1次
save 300 10 #5分钟内修改了10次
save 60 10000 #1分钟内修改了10000次

当达到条件时会触发bgsave命令

这个我测试了一下 save 300 3表示的是自上次生成rdb快照后,300s内如果有3次更改,在300s的时间节点时会触发一次bgsave命令,而不是写入3次后就立马触发

手动触发快照

  • save 命令:由主线程执行,会阻塞所有客户端请求(直到快照完成),生产环境慎用
  • bgsave 命令:后台执行(background save),fork 子进程处理快照,主线程继续响应请求,不阻塞服务。
阅读全文 »

Redis 核心优势及典型应用场景

Redis 作为高性能的键值对数据库,凭借其独特的设计和特性,在缓存、计数、实时排行榜等场景中被广泛应用。本文深入解析 Redis 为何能实现高速读写,并详细介绍其核心应用场景。

Redis 高性能的三大核心原因

Redis 之所以能支持每秒数万甚至数十万的读写操作,核心源于以下三点设计:

1. 基于内存的操作

  • 数据存储在内存中:Redis 将所有数据存储在内存(RAM)中,而内存的读写速度(微秒级)远高于磁盘(毫秒级)。
  • 避免磁盘 I/O 瓶颈:传统数据库(如 MySQL)需要频繁读写磁盘,而 Redis 的数据操作几乎不涉及磁盘 I/O(持久化操作除外,且可异步执行),因此延迟极低。

2. 单线程模型,避免上下文切换

  • 单线程处理命令:Redis 采用单线程模型处理所有客户端的命令请求(持久化、集群同步等操作由额外线程执行)。
  • 无上下文切换开销:多线程模型中,线程切换需要保存和恢复上下文(如寄存器状态、程序计数器),会消耗 CPU 资源;而单线程避免了这一开销,确保命令执行的连续性。
  • 注意:单线程不意味着 “并发能力差”,Redis 通过非阻塞 I/O 机制支持高并发(见下文)。

3. 非阻塞 I/O 多路复用机制

  • I/O 多路复用:Redis 使用 selectepoll(Linux)、kqueue(macOS)等 I/O 多路复用函数,允许单线程同时监听多个客户端连接的 I/O 事件(如 “可读”“可写”)。
  • 高效处理并发请求:当多个客户端同时发送请求时,Redis 无需为每个连接创建线程,而是通过事件循环(Event Loop)高效处理所有请求,避免了多线程的资源竞争。

Redis 的典型应用场景

Redis 的高性能和丰富的数据结构(字符串、哈希、列表、集合、有序集合等)使其适用于多种场景:

1. 缓存系统(最核心场景)

阅读全文 »
0%