1. 做三个节点的redis集群。

编辑redis节点node0(10.0.0.100)、node1(10.0.0.101)、node2(10.0.0.102)的安装脚本

[root@node0 ~]# vim install_redis.sh
 
#!/bin/bash
# 指定脚本解释器为bash
 
REDIS_VERSION=redis-7.2.4
# 定义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

构建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.101:/root
# 将脚本复制到node1
[root@node2  ~]# scp install_redis.sh  10.0.0.102:/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.101:6379   10.0.0.102:6379”
# 使用redis-cli命令创建Redis集群,包含node0、node1和node2上的Redis实例
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
M: f1802218db4531421a9cf1b8cdcf7aa452da0ff4 10.0.0.100:6379
   slots:[0-5460] (5461 slots) master
M: 5ef01641ba84ad520f82a5d9b67d50a121af560c 10.0.0.101:6379
   slots:[5461-10922] (5462 slots) master
M: 48521f26ebbfceea42ddb2904686599515ba83c0 10.0.0.102:6379
   slots:[10923-16383] (5461 slots) master

2. 总结redis持久化的两种方式和原理

Redis持久化是指将内存中的数据保存到硬盘,以防止服务器宕机导致数据丢失的机制。Redis提供了两种持久化的方式,分别是RDB(Redis DataBase)和AOF(Append Only File),以下是这两种持久化方式的原理总结:

一、RDB持久化
原理:RDB持久化是一种快照式的持久化方法,它会在某个时间点将内存中的数据生成快照并存储到磁盘等介质上。这个过程是通过rdbSave函数实现的,它会遍历内存中的所有键值对,并将它们序列化后写入到一个二进制文件中,这个文件通常被称为RDB文件,默认文件名为dump.rdb。当Redis重新启动时,它会读取RDB文件中的数据,并通过rdbLoad函数将数据重新载入到内存中。
触发机制:RDB持久化可以通过手动触发和自动触发两种方式来实现。手动触发可以通过执行SAVE或BGSAVE命令来完成。SAVE命令会阻塞Redis主线程,直到RDB文件创建完成,而BGSAVE命令则会在后台创建一个子进程来执行RDB文件的创建过程,不会阻塞主线程。自动触发则是通过配置Redis配置文件中的save选项来实现的,当满足指定的时间间隔和修改次数条件时,Redis会自动执行BGSAVE命令。
优缺点:
优点:RDB文件是一个紧凑的二进制文件,文件体积小,加载速度快,适合数据的容灾备份与恢复。
缺点:RDB持久化是间隔一段时间进行一次持久化,如果Redis在两次持久化之间发生故障,则最后一次持久化后的数据就会丢失。此外,在fork创建的子进程进行RDB持久化过程中,子进程会占用与父进程相同的内存资源,可能会导致Redis性能下降。
二、AOF持久化
原理:AOF持久化是通过记录Redis服务器所执行的写命令来记录数据库状态的。AOF文件以追加的方式记录Redis所执行过的所有修改的命令,将每一条修改命令记录进文件appendonly.aof中。当Redis重新启动时,它会读取AOF文件并重新执行文件中的写命令来恢复内存数据。
写回策略:AOF持久化功能实现主要分为命令追加、文件写入、文件同步、文件重写和重启加载五个部分。其中,文件同步策略可以通过appendfsync参数来设置,有三种策略可选:
appendfsync always:每次有新命令写入到AOF缓冲区时,执行一次fsync将命令追加到AOF文件中,非常慢,也非常安全。
appendfsync everysec:每次写命令写入到aof_buf后,每隔一秒同步到磁盘(默认设置推荐),足够快并且在故障时只会丢失1秒的数据。
appendfsync no:每次写命令写入到aof_buf后,从不fsync,将数据交给操作系统来处理,更快,也更不安全。
文件重写:随着服务器运行时间增加,AOF文件会越来越大,这会影响Redis重启时间。因此Redis提供了AOF重写机制,通过创建一个新的AOF文件来替代旧文件,新文件只包含恢复当前数据集所需的最小命令集。重写过程也是异步进行的,并且不会阻塞Redis处理新命令。
优缺点:
优点:AOF持久化提供多种持久化策略,可以根据需要选择合理的策略;AOF文件是一个纯文本文件,易于理解、修改和恢复;对于误操作的数据可以通过修改AOF文件来恢复;数据更加安全,即使出现宕机,也只是丢失最近一次AOF文件写入之后的数据。
缺点:AOF文件通常比RDB文件大,恢复速度慢;AOF文件写入性能通常比RDB差,特别是有大量写入操作的场景下。
综上所述,RDB和AOF是Redis提供的两种持久化方式,它们各有优缺点。在实际应用中,可以根据具体需求选择适合的持久化方式或同时启用两种方式以确保数据的安全性和完整性。

3.从内核事件原理层面阐述为什么redis这么快

Redis之所以能够在性能上表现出色,从内核事件原理层面来看,主要归因于以下几个关键因素:

一、内存存储
Redis将数据存储在内存中,这是其性能优势的根本。内存的读写速度远远快于磁盘,因此Redis能够实现极低的读写延迟。这种架构使Redis非常适合那些频繁读取和写入的场景,如缓存系统、会话管理和实时排行榜等。

二、单线程模型与事件驱动机制
Redis采用单线程模型,这意味着它一次只处理一个请求。然而,Redis通过高效的事件驱动机制来应对高并发。它使用了一个事件循环(Event Loop)来管理多个连接,并结合了IO多路复用技术(如epoll)。这种设计在降低上下文切换和锁机制的开销方面效果显著。

单线程处理:Redis的所有操作在单线程中完成,避免了多线程的锁机制问题,降低了上下文切换的开销。多线程编程常常需要引入锁机制来防止数据竞争,而Redis通过单线程架构消除了这一复杂性,减少了系统的负担。
IO多路复用:Redis使用了IO多路复用机制,允许一个线程同时监控多个文件描述符(即多个连接)。一旦某个连接的状态发生变化(比如有新数据可读或写),该线程就会立即处理该事件。这样,Redis可以高效地处理大量客户端连接,提升了整体吞吐量。
三、高效的数据结构设计
Redis支持多种高效的数据结构,包括字符串(String)、列表(List)、集合(Set)、有序集合(Sorted Set)、哈希(Hash)等。Redis为这些数据结构做了专门的优化,确保它们在执行插入、查找、更新等操作时都能达到最佳性能。

SDS(Simple Dynamic Strings,简单动态字符串):Redis使用SDS结构来管理字符串,支持O(1)的字符串长度查询和动态扩展。SDS结构会预先分配空间并记录未使用的空间,以减少频繁的内存分配和释放操作,提升性能。
跳表(Skip List):Redis在有序集合中采用了跳表来存储数据。跳表是一种分层结构,支持高效的范围查询和插入操作。相比于传统的链表结构,跳表在多层索引的帮助下,可以快速地定位和访问节点,适合有序数据的高效操作。
压缩列表(ZipList):在Redis的链表、哈希表等数据结构中,Redis使用压缩列表来存储小型数据集。压缩列表是一种紧凑的内存结构,能够减少内存占用,提高数据的缓存效率。
四、持久化机制
虽然Redis主要是一个内存数据库,但它也支持将数据持久化到磁盘,以确保数据的可靠性。Redis提供了两种持久化选项:快照(snapshot)和日志(append-only file)。这些机制确保了即使在服务器重启时,数据也不会丢失,从而满足了一些需要持久化数据的应用场景。

五、高效的通信协议
Redis使用了一种简单且高效的RESP(REdis Serialization Protocol,Redis序列化协议)协议。RESP协议设计简单,传输数据高效,支持字符串、整型、数组、错误等多种数据类型。在客户端和服务器之间的通信中,RESP通过简洁的指令和数据格式,减少了数据的传输和解析开销,提升了数据传输的效率。

综上所述,Redis之所以能够在性能上表现出色,主要得益于其基于内存的存储设计、单线程模型与事件驱动机制、高效的数据结构设计、持久化机制以及高效的通信协议等多个方面的优势。这些优势共同作用,使得Redis成为了一个高性能的键值存储系统,广泛应用于各种应用场景。

Logo

一站式 AI 云服务平台

更多推荐