主页 > 电脑硬件  > 

Linux云计算SRE-第十七周

Linux云计算SRE-第十七周
1. 做三个节点的redis集群。

1、编辑redis节点node0(10.0.0.100)、node1(10.0.0.110)、node2(10.0.0.120)的安装脚本

[root@node0 ~]# vim install_redis.sh #!/bin/bash # 指定脚本解释器为bash REDIS_VERSION=redis-7.2.7 # 定义Redis的版本号 PASSWORD=123456 # 设置Redis的访问密码 INSTALL_DIR=/apps/redis # 指定Redis的安装目录 CPUS=$(lscpu | awk '/^CPU\(s\)/{print $2}') # 获取CPU核心数量,用于编译时的并行处理 . /etc/os-release # 加载系统发行版信息 color () { # 定义一个函数,用于输出彩色文本信息 RES_COL=60 MOVE_TO_COL="echo -en \\033[${RES_COL}G" SETCOLOR_SUCCESS="echo -en \\033[1;32m" SETCOLOR_FAILURE="echo -en \\033[1;31m" SETCOLOR_WARNING="echo -en \\033[1;33m" SETCOLOR_NORMAL="echo -en \E[0m" echo -n "$1" && $MOVE_TO_COL echo -n "[" if [ $2 = "success" -o $2 = "0" ] ;then ${SETCOLOR_SUCCESS} echo -n $" OK " elif [ $2 = "failure" -o $2 = "1" ] ;then ${SETCOLOR_FAILURE} echo -n $"FAILED" else ${SETCOLOR_WARNING} echo -n $"WARNING" fi ${SETCOLOR_NORMAL} echo -n "]" echo } prepare(){ # 准备安装环境,安装Redis编译所需的依赖包 if [ $ID = "centos" -o $ID = "rocky" ];then yum -y install gcc make jemalloc-devel systemd-devel else apt update apt -y install gcc make libjemalloc-dev libsystemd-dev fi if [ $? -eq 0 ];then color "安装软件包成功" 0 else color "安装软件包失败,请检查网络配置" 1 exit fi } install() { # 安装Redis if [ ! -f ${REDIS_VERSION}.tar.gz ]; then # 如果Redis源码包不存在,则下载 wget http://download.redis.io/releases/${REDIS_VERSION}.tar.gz || { color "Redis 源码下载失败" 1; exit; } fi tar xf ${REDIS_VERSION}.tar.gz -C /usr/local/src # 解压源码包到/usr/local/src cd /usr/local/src/${REDIS_VERSION} # 进入解压后的目录 make -j $CPUS USE_SYSTEMD=yes PREFIX=${INSTALL_DIR} install && color "Redis 编译安装完成" 0 || { color "Redis 编译安装失败" 1; exit; } # 编译并安装Redis,使用CPU核心数量加速编译 ln -s ${INSTALL_DIR}/bin/redis-* /usr/local/bin/ # 创建Redis命令的软链接到/usr/local/bin mkdir -p ${INSTALL_DIR}/{etc,log,data,run} # 创建Redis所需的目录结构 cp redis.conf ${INSTALL_DIR}/etc/ # 复制Redis配置文件到安装目录的etc子目录 sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' \ -e "/# requirepass/a requirepass $PASSWORD" \ -e "/^dir .*/c dir ${INSTALL_DIR}/data/" \ -e "/logfile .*/c logfile ${INSTALL_DIR}/log/redis-6379.log" \ -e "/^pidfile .*/c pidfile ${INSTALL_DIR}/run/redis_6379.pid" ${INSTALL_DIR}/etc/redis.conf # 修改Redis配置文件,设置密码、数据目录、日志文件和PID文件路径 if id redis &> /dev/null; then color "Redis 用户已存在" 1 else useradd -r -s /sbin/nologin redis color "Redis 用户创建成功" 0 fi # 检查Redis用户是否存在,不存在则创建 chown -R redis.redis ${INSTALL_DIR} # 更改Redis安装目录的拥有者为redis用户 cat >> /etc/sysctl.conf <<EOF net.core.somaxconn = 1024 vm.overcommit_memory = 1 EOF sysctl -p # 修改系统内核参数并应用 if [ $ID = "centos" -o $ID = "rocky" ]; then echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local chmod +x /etc/rc.d/rc.local /etc/rc.d/rc.local else echo -e '#!/bin/bash\necho never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local chmod +x /etc/rc.local /etc/rc.local fi # 禁用透明大页,根据系统类型选择不同的方法 cat > /lib/systemd/system/redis.service <<EOF [Unit] Description=Redis persistent key-value database After=network.target [Service] ExecStart=${INSTALL_DIR}/bin/redis-server ${INSTALL_DIR}/etc/redis.conf --supervised systemd ExecStop=/bin/kill -s QUIT \$MAINPID Type=notify User=redis Group=redis RuntimeDirectory=redis RuntimeDirectoryMode=0755 LimitNOFILE=1000000 [Install] WantedBy=multi-user.target EOF # 创建Redis的systemd服务文件 systemctl daemon-reload systemctl enable --now redis &> /dev/null # 重新加载systemd配置,并启用Redis服务 if [ $? -eq 0 ]; then color "Redis 服务启动成功,Redis信息如下:" 0 else color "Redis 启动失败" 1 exit fi # 检查Redis服务是否启动成功,并输出相应信息 sleep 2 redis-cli -a $PASSWORD INFO Server 2> /dev/null # 等待2秒,然后使用redis-cli获取Redis服务器信息 } prepare # 调用prepare函数准备环境 install # 调用install函数安装Redis

 2、构建redis节点node0(10.0.0.100)、node1(10.0.0.101)、node2(10.0.0.102)的集群。

[root@node0 ~]# bash install_redis.sh # 执行install_redis.sh脚本以安装Redis [root@node0 ~]# sed -i.bak -e '/masterauth/a masterauth 123456' -e '/# cluster-enabled yes/a cluster-enabled yes' -e '/# cluster-config-file nodes-6379.conf/a cluster-config-file nodes-6379.conf' -e '/cluster-require-full-coverage yes/a cluster-require-full-coverage no' /apps/redis/etc/redis.conf # 使用sed命令修改Redis配置文件,启用密码认证、集群模式等 [root@node0 ~]# systemctl restart redis # 重启Redis服务以应用配置更改 # 以下命令用于在其他节点上复制脚本、安装Redis并配置集群模式 [root@node1 ~]# scp install_redis.sh 10.0.0.110:/root # 将脚本复制到node1 [root@node2 ~]# scp install_redis.sh 10.0.0.120:/root # 将脚本复制到node2 [root@node1 ~]# bash install_redis.sh # 在node1上执行脚本安装Redis [root@node1 ~]# sed -i.bak -e '/masterauth/a masterauth 123456' -e '/# cluster-enabled yes/a cluster-enabled yes' -e '/# cluster-config-file nodes-6379.conf/a cluster-config-file nodes-6379.conf' -e '/cluster-require-full-coverage yes/a cluster-require-full-coverage no' /apps/redis/etc/redis.conf # 修改node1上的Redis配置 [root@node1 ~]# systemctl restart redis # 重启node1上的Redis服务 [root@node2 ~]# bash install_redis.sh # 在node2上执行脚本安装Redis [root@node2 ~]# sed -i.bak -e '/masterauth/a masterauth 123456' -e '/# cluster-enabled yes/a cluster-enabled yes' -e '/# cluster-config-file nodes-6379.conf/a cluster-config-file nodes-6379.conf' -e '/cluster-require-full-coverage yes/a cluster-require-full-coverage no' /apps/redis/etc/redis.conf # 修改node2上的Redis配置 [root@node2 ~]# systemctl restart redis # 重启node2上的Redis服务 [root@node0 ~]# redis-cli -a 123456 --cluster create 10.0.0.100:6379 10.0.0.110:6379 10.0.0.120:6379 # 使用redis-cli命令创建Redis集群,包含node0、node1和node2上的Redis实例 Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. >>> Performing hash slots allocation on 3 nodes... Master[0] -> Slots 0 - 5460 Master[1] -> Slots 5461 - 10922 Master[2] -> Slots 10923 - 16383 M: 6a1fcf17824b5b05000d222d4f5fc54f5eb95ba3 10.0.0.100:6379 slots:[0-5460] (5461 slots) master M: f54c4e03dd0e6d6c64804a0645d28a17012ffe16 10.0.0.110:6379 slots:[5461-10922] (5462 slots) master M: 4c2d7e08d91d439b00f7d692269afc8073bd1597 10.0.0.120:6379 slots:[10923-16383] (5461 slots) master Can I set the above configuration? (type 'yes' to accept): yes >>> Nodes configuration updated >>> Assign a different config epoch to each node >>> Sending CLUSTER MEET messages to join the cluster Waiting for the cluster to join >>> Performing Cluster Check (using node 10.0.0.100:6379) M: 6a1fcf17824b5b05000d222d4f5fc54f5eb95ba3 10.0.0.100:6379 slots:[0-5460] (5461 slots) master M: 4c2d7e08d91d439b00f7d692269afc8073bd1597 10.0.0.120:6379 slots:[10923-16383] (5461 slots) master M: f54c4e03dd0e6d6c64804a0645d28a17012ffe16 10.0.0.110:6379 slots:[5461-10922] (5462 slots) master [OK] All nodes agree about slots configuration. >>> Check for open slots... >>> Check slots coverage... [OK] All 16384 slots covered. [root@node0 ~]#redis-cli -a 123456 -c INFO replication Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:4f5c6acc29267a7c0abb5d99683fbb122b77c816 master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 [root@node1 ~]#redis-cli -a 123456 -c INFO replication Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:273975d582c1f2dcce034819de2d425e085c550c master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 [root@node2 ~]#redis-cli -a 123456 -c INFO replication Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe. # Replication role:master connected_slaves:0 master_failover_state:no-failover master_replid:0e495f096ccffdace37cd7c452c3f6c5db44e69e master_replid2:0000000000000000000000000000000000000000 master_repl_offset:0 second_repl_offset:-1 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 2. 总结redis持久化的两种方式和原理

Redis 持久化是将内存数据存储到硬盘,防止服务器宕机导致数据丢失的机制,主要提供 RDB 和 AOF 两种方式:

一、RDB 持久化

原理: 1、快照式持久化:在特定时间点生成内存数据的二进制快照(RDB 文件,默认 dump.rdb),通过 rdbSave 函数将数据序列化写入文件。重启时通过 rdbLoad 函数加载数据到内存。 2、触发机制: - 手动触发:          SAVE:阻塞主线程生成快照,影响服务。          BGSAVE:后台 fork 子进程生成快照,不阻塞主线程。 - 自动触发:通过配置文件 save <seconds> <changes> 设置条件(如 save 900 1 表示 900 秒内至少 1 次修改触发)。 优缺点: 优点:         文件紧凑(二进制压缩),加载速度快,适合备份与灾难恢复。 缺点:         数据可能丢失(两次快照间的修改未持久化)。         大数据量时 fork 子进程可能占用较多内存,影响性能。

二、AOF 持久化

原理: - 命令追加式持久化:记录所有写操作命令到文本文件(默认 appendonly.aof),重启时重放命令恢复数据。 - 写回策略(通过 appendfsync 配置):          always:每次写操作同步写入磁盘,数据最安全但性能最低。          everysec(默认):每秒批量同步,平衡安全与性能(最多丢失 1 秒数据)。          no:依赖操作系统同步,性能最高但数据风险最大。 - 文件重写:          目的:压缩冗余命令(如多次 set 同一键),生成更小的新 AOF 文件。          实现:后台异步执行,不影响主线程处理新命令。 优缺点: 优点:         数据安全性高(可配置实时/准实时持久化)。         文件可读性强,支持手动修复或恢复误操作。 缺点:         文件体积较大,恢复速度慢于 RDB。         高并发写入时可能影响性能(尤其是 always 模式)。

三、总结 对比项RDBAOF数据安全性可能丢失部分数据更高(依赖策略)文件大小小(二进制压缩)大(文本记录命令)恢复速度快(直接加载内存快照)慢(逐条执行命令)性能影响fork 子进程可能占用内存频繁写入可能增加 I/O 压力

实际应用建议:

高安全性场景:启用 AOF(everysec 模式)。快速恢复场景:启用 RDB。综合方案:同时开启 RDB + AOF(RDB 用于定期备份,AOF 保障实时数据安全)。 3.从内核事件原理层面阐述为什么redis这么快

        Redis的极致性能来源于多个层面的协同优化,尤其在内核事件处理机制上表现突出。从内核事件原理层面来看,主要归因于以下几个关键因素:

一、内存存储:内核访问的物理基础

        Redis 将数据存储在内存中,内存的直接访问速度是磁盘的 10^5~10^6 倍,避免了磁盘 I/O 的阻塞问题。

内核与内存协作: 内核通过页缓存(Page Cache)和直接内存映射(mmap)机制管理内存,Redis无需频繁与磁盘交互,所有操作均在用户态内存中完成,减少了系统调用和上下文切换次数。

零拷贝优化: 当 Redis 响应客户端请求时,数据从内存直接写入内核的套接字缓冲区(Socket Buffer),通过sendfile或writev系统调用实现零拷贝传输,减少数据在内核态与用户态之间的复制开销。

二、单线程模型与事件驱动:内核事件的高效调度

        Redis 采用 单线程 Reactor 模式,结合 I/O 多路复用技术,最大化利用内核的事件通知机制。

I/O 多路复用的内核实现:

使用 epoll(Linux)或 kqueue(BSD)监听所有客户端连接的套接字。

当某个套接字就绪(可读/可写)时,内核通过事件回调通知 Redis 主线程,触发对应的文件事件处理器。

优势:

水平触发(LT):确保事件不丢失,适合 Redis 的请求处理模式。

边缘触发(ET):减少重复通知,提升效率。

单线程的优势:

零锁竞争:无需处理多线程的锁同步问题,避免死锁和上下文切换开销。

无阻塞操作:所有操作(命令执行、响应发送)均非阻塞,主线程专注于事件循环。

事件循环(aeEventLoop):

核心流程:

通过 epoll_wait 监听就绪事件。

将事件分发给对应的处理器(如命令请求处理器、命令回复处理器)。

处理完所有就绪事件后,检查时间事件(如定时任务)。

优先级策略:优先处理文件事件(用户请求),确保实时性。

三、高效数据结构:减少内核交互开销

        Redis 的数据结构设计以内存高效访问和低系统调用频率为目标:

SDS(简单动态字符串):

预分配内存空间,减少 malloc 系统调用次数。

记录字符串长度,避免遍历计算长度(O(1) 时间复杂度)。

跳表(Skip List):

多层索引结构加速范围查询,减少遍历次数。

内存连续访问模式,提升 CPU 缓存命中率。

压缩列表(ZipList):

紧凑内存布局,减少内存碎片和缺页中断(Page Fault)概率。

四、持久化机制:内核的异步协作

        Redis 通过fork子进程实现 RDB 和 AOF 持久化,利用内核的写时复制(Copy-On-Write)机制:

RDB 快照:

子进程通过fork创建,共享父进程内存页。

内核在父进程修改内存时触发写时复制,子进程独立持久化数据,避免阻塞主线程。

AOF 日志:

主线程将命令追加到内核缓冲区,子进程异步刷盘,通过 fsync 控制同步策略(如 everysec 平衡性能与安全)。

五、通信协议:内核缓冲区的批量处理

        Redis 使用 RESP 协议,通过批量数据格式减少网络传输次数:

批量数据格式:将多个命令或响应合并传输,减少 read/write 系统调用次数。

内核缓冲区优化:

客户端请求和响应数据先写入内核缓冲区,由内核异步完成网络传输,避免主线程阻塞。

通过TCP_CORK 或 Nagle 算法合并小包,减少网络报文数量。

优化维度内核事件原理的体现性能收益内存存储避免磁盘 I/O 阻塞,依赖内核页缓存和零拷贝技术读写延迟低至微秒级单线程与事件驱动基于 epoll 的事件通知机制,无锁无上下文切换单线程吞吐量达 10W+ QPS数据结构减少内存碎片和系统调用,提升 CPU 缓存命中率复杂操作(如范围查询)效率高持久化子进程与写时复制(COW)机制,避免主线程阻塞持久化过程对服务影响极小通信协议批量数据格式 + 内核缓冲区异步传输网络传输效率高,延迟波动小

        综上所述,Redis之所以能够在性能上表现出色,主要得益于其基于内存的存储设计、单线程模型与事件驱动机制、高效的数据结构设计、持久化机制以及高效的通信协议等多个方面的优势。Redis 通过内核事件机制的高效调度,结合内存存储、单线程模型和数据结构优化,在高并发、低延迟、高吞吐场景下表现卓越,成为内存数据库的标杆。 

标签:

Linux云计算SRE-第十七周由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Linux云计算SRE-第十七周