Redis基础&&集群

redis---缓存服务

mysql 关系型数据量
redis,mongo,es 非关系型数据量

一、redis基础

1、redis特点、

- 数据读取快,(数据都存放在内存中,使用C语言实现,使用单线程架构)
- 多种数据结构
- 功能丰富
- 简单稳定
- 客户端语言多
- 持久化
- 主从复制
- 高可用和分布式

2、应用场景

- 键过期功能: 缓存, session回话保存,优惠劵过期
- 列表:排行榜
- 天然计数器:浏览数、点击数、评论数
- 集合:兴趣标签、广告投放
- 消息队列: ELK

3、redis安装部署

- 目录规划:
    redis下载目录
    /tools/
    redis安装目录
    /opt/redis_cluster/redis_[port]/{conf,logs,pid}
    redis数据目录
    /data/redis_cluster/redis_[port]/redis_[port].rdb
    redis运维脚本
    /scripts/
- 部署安装:
    #创建对应的目录
    ##6379为redis默认端口
    mkdir -p /data/redis_cluster/redis_6379
    mkdir -p /opt/redis_cluster/redis_6379/{conf,pid,logs}
    mkdir /tools
    #下载对应的软件包
    cd /tools
    wget https://download.redis.io/releases/redis-3.2.9.tar.gz
    #解压对应的软件包到/opt/下
    tar zxf redis-3.2.9.tar.gz -C /opt/redis_cluster/
    #创建软连接,方便后续升级或者脚本维护
    ln -s /opt/redis_cluster/redis-3.2.9/ /opt/redis_cluster/redis
    #编译安装
    cd /opt/redis_cluster/redis
    make && make install

4、配置文件介绍

- 配置文件查找
    找到对应的版本包,进入对应的目录下
    redis-3.2.9/utils
    执行对应的install_server.sh  根据提示 就可以再对应目录生成配置文件

- 本文使用配置文件
    ### 以守护进程模式启动
    daemonize yes
    ### 绑定的主机地址(默认绑定内网网卡的地址)
    bind 10.0.0.181
    ### 监听端口
    port 6379
    ### pid文件和log文件的保存地址
    pidfile /opt/redis_cluster/redis_6379/pid/redis_6379.pid
    logfile /opt/redis_cluster/redis_6379/logs/redis_6379.log
    ### 设置数据量的数量,默认数据量为0
    databases 16
    ### 指定本地之九华文件的文件名,默认是dump.rdb
    dbfilename redis_6379.rdb
    ### 本地数据库的目录
    dir /data/redis_cluster/redis_6379
- 启动关闭服务 ,
    #启动
    redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf
    #登录
    #默认登录 127.0.0.1
    redis-cli
    #-h 指定ip登录 
    redis-cli -h ip
    #关闭
      #直接登录命令后面接 shutdown
      redis-cli -h ip shutdown
      #登录后,输入shutdown
      redis-cli
      shutdown

5、redis基础命令

- 全局命令
    1、查看所有命键
        keys *
        # 十分危险命令,线上禁止使用,redis在内存中,数据量过大会导致redis直接卡死,挂掉
    2、查看键的总数
        DBSIZE
        # dbsize命令在计算键总数是不会遍历所有键,而是直接获取redis内置的键总数的变量
    3、检查键是否存在
        EXISTS key
        #如果键存在则返回1.不存在则返回0
    4、删除键
        DEL key [key ...]
        # 通用命令,无论值是什么数据结构类型,del命令都可以将其删除
    5、查看过期时间
        #语法 TTL key
        ## TTL对应的值
        -1 永不过期
        -2 没有这个key

    5、键过期时间设置
        #语法 EXPIRE key seconds

        db01:6379> EXPIRE k6 200
        (integer) 1
        db01:6379> TTL k6
        (integer) 193
        db01:6379> TTL k6
        (integer) 193
        db01:6379> TTL k6
        (integer) 192

        ##生产事故注意  ,如果设置完过期时间,重新设置了key值,过期时间为永不失效
        db01:6379> set k6 123
        OK
        db01:6379> TTL k6
        (integer) -1
    6、取消过期时间设置
        #语法: PERSIST key
        db01:6379> PERSIST k6
        (integer) 1
        db01:6379> TTL k6
        (integer) -1
    7、查询key的类型
    #语法 TYPE key
        db01:6379> TYPE k1
        string
        db01:6379> TYPE k2
        string
- 字符串
    1、设置一个key 并赋值
    #语法 SET key value
        db01:6379> set k1 2
        OK
        db01:6379> set k2 zhangxl
        OK
    2、查询key的值
    #语法 GET key
        db01:6379> get k1
        "2"
        db01:6379> get k2
        "zhangxl"
    3、设置多个key 并复制
    #语法 MSET key value [key value ...]
        db01:6379> MSET k4 4 k5 5 k6 6
        OK
    4、查询多个key 
    #语法 MGET key [key ...]
        db01:6379> MGET k4 k5 k6
        1) "4"
        2) "5"
        3) "6"
    5、INCR 计数器。命令蒋字符串值解析成整数型,将其加1,最后结果保存为新的字符串,类似命令 INCRBY DECR DECRBY
        db01:6379> SET K3 100
        OK
        db01:6379> GET K3
        "100"
        db01:6379> INCR K3
        (integer) 101
        db01:6379> INCR K3
        (integer) 102
        db01:6379> INCR K3
        (integer) 103
        db01:6379> INCRBY K3 1000
        (integer) 1103
        db01:6379> GET K3
        "1103"
- 列表
    1、添加列表元素
        #从右插入列表元素
            db01:6379> RPUSH list1 1
            (integer) 1
            db01:6379> RPUSH list1 2
            (integer) 2
            db01:6379> RPUSH list1 A
            (integer) 3
            db01:6379> RPUSH list1 B
            (integer) 4
        #从左插入列表元素
            db01:6379> LPUSH list1 C
            (integer) 5
            db01:6379> LPUSH list1 D
            (integer) 6
        #批量插入列表元素
            db01:6379> RPUSH list1 3 4 5 6 7 8 
            (integer) 10
            db01:6379> LRANGE list1 0 -1
             1) "C"
             2) "1"
             3) "2"
             4) "A"
             5) "3"
             6) "4"
             7) "5"
             8) "6"
             9) "7"
            10) "8"
    2、查看列表的元素
        #查看列表的元素值 语法: LRANGE key start stop (查询所有 去一个不存在的反馈,查询单个 进行精确)
            db01:6379> LRANGE list1 0 -1
            1) "D"
            2) "C"
            3) "1"
            4) "2"
            5) "A"
            6) "B"

            db01:6379> LRANGE list1 0 1
            1) "D"
            2) "C"
            db01:6379> LRANGE list1 0 0
            1) "D"
        #查看列表的元素数量
        db01:6379> LLEN list1
        (integer) 6
    3、删除列表元素
        #从右删除列表元素
            db01:6379> RPOP list1
            "B"
            db01:6379> LRANGE list1 0 -1
            1) "D"
            2) "C"
            3) "1"
            4) "2"
            5) "A"
        #从左删除列表元素
            db01:6379> lpop list1
            "D"
            db01:6379> LRANGE list1 0 -1
            1) "C"
            2) "1"
            3) "2"
            4) "A"
- 哈希
    1、插入key数据
        #语法: HMSET key field value [field value ...]
        db01:6379> HMSET user:1000 name zxl age 28 job it
        OK
    2、查询key数据
        ###查询key指定的数据
        #语法:HMGET key field [field ...]
            db01:6379> HMGET user:1000 name
            1) "zxl"
            db01:6379> HMGET user:1000 name age job
            1) "zxl"
            2) "28"
            3) "it"
        ###查询key所有的数据
        #语法: HGETALL key
            db01:6379> HGETALL user:1000
            1) "name"
            2) "zxl"
            3) "age"
            4) "28"
            5) "job"
            6) "it"
- 集合
    1、设置集合的数据 (set集合不允许出现重复的元素)
        #语法 SADD key member [member ...]
            db01:6379> SADD set1 1 3 5 7 9
            (integer) 5
            db01:6379> SADD set2 1 3 5 2 4 6
            (integer) 6
    2、查询集合的数据
        #语法 SMEMBERS key
            db01:6379> SMEMBERS set1
            1) "1"
            2) "3"
            3) "5"
            4) "7"
            5) "9"
            db01:6379> SMEMBERS set2
            1) "1"
            2) "2"
            3) "3"
            4) "4"
            5) "5"
            6) "6"
    3、删除集合指定的值
        #语法 SREM key member [member ...]
            db01:6379> SMEMBERS set2
            1) "1"
            2) "2"
            3) "3"
            4) "4"
            5) "5"
            6) "6"
            db01:6379> SREM set2 1 3
            (integer) 2
            db01:6379> SMEMBERS set2
            1) "2"
            2) "4"
            3) "5"
            4) "6"
    4、查询2个不同集合的差异数据 以第一个key为基准,找出第一个集合有 第二个集合没有 的数据
        #语法
            db01:6379> SDIFF set1 set2
            1) "1"
            2) "3"
            3) "7"
            4) "9"

            db01:6379> SDIFF set2 set1
            1) "2"
            2) "4"
            3) "6"
    5、查询2个不同集合的并集数据
        #语法 SINTER key [key ...]
            db01:6379> SINTER set1 set2
            1) "5"
    6、查询2个不同集合的所有数据
        #语法 SUNION key [key ...]
            db01:6379> SUNION set1 set2
            1) "1"
            2) "2"
            3) "3"
            4) "4"
            5) "5"
            6) "6"
            7) "7"
            8) "9"

6、数据持久化

- RDB持久化
    #bgsave命令
        db01:6379> BGSAVE
        Background saving started
        #查询之九华目录 已经存在对应的文件。再次关闭redis,打开数据还在 不会丢失,但是如果新插入数据,没有bgsave 新的数据丢失
    - 优点
        1、RDB是一个紧凑压缩的二进制文件,代表Redis在某个时间点上的数据快照,分成适用于备份,全量复制等场景,比如每6小时行bgsave本分,并把RBD文件拷贝到远程机器,用于灾难恢复
        2、Redis加载RDB恢复数据远远快鱼AOF的方式
    - 缺点
        1、RDB方式数据没办法做到实时持久化,秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作,行频繁成本过高
        2、RDB文件使用特定二进制格式保存,Redis版本严禁过程中有多个格式的RDB版本,存在老版本Redis不兼容新版RDB格式的问题

    - #配置文件添加指定的参数
        ### 指定本地持久化文件的文件名,默认是dump.rdb 指定多久发生变化保存  900秒 1个可以发生改变,保存
        save 900 1  #900秒 发生一个key值改变
        save 300 10 #300秒 发生10个key值改变
        save 60 10000 #60秒 发生10000个key值改变
        dbfilename redis_6379.rdb
    ###注意!!!!
    - 如果什么条件都没达成,正常关闭了redis,后端会操作  bgsavs   shutdown 数据会持久化
    - 如果什么条件都没达成,kill pkill kill -15 优雅的关闭了redis,后端操作和正常关闭redis操作一直
    - 如果什么条件都没达成,kill -9 关闭redis,程序会直接关闭,数据不会持久化,
- AOF持久化
    - 工作流程
      记录服务器执行的所有写操作命令,并在服务器启东市,通过重新执行这些命令来还原数据
      AOF文件中的命令全部以Redis协议的格式来保存,新明路会被追加到文件的末尾
        1、所有写入命令会追加到aof buf(缓冲区)
        2、AOF缓冲区根据对应的策略想硬盘做同步操作
        3、随着AOF文件越来越大,需要定期对AOF文件进行重写,大道压缩
        4、当Redis服务重启时,可以加载AOF文件进行数据恢复
    
    !!!如果存在aof和rdb备份同事存在,优先读取aof
    - 缺点:
        日志记录量比较大
    - 有点:
        安全。最多丢失1秒数据
    - 配置文件:
        #是否打开aof日志功能
        appendonly yes
        #每一个命令,都立即同步到aof
        appendfsync always
        #每秒写入一次
        appendfsync everysec
        #写入工作交给操作系统,由操作判断缓冲区大小,同意写入到aof
        appendfsync no
        #定义文件的名称
        appendfilename "appendonly.aof"
- 面试问题
    redis持久化方式有那些,有什么区别?
    RDB : 基于快照的持久化,速度更快,一般用作备份,主从复制也是依赖于rdb持久化功能
    AOF : 一追加的方式记录redis操作日志的文件,可以最大程度的保证redis数据安全,类似于mysql和binlog

7、redis 认证

- redis默认开启了保护模式,只允许本地会还地址登录并访问数据量
    禁止 protected-mode
    protected-mode yes/no (保护模式,是否只允许本地访问)
    1)Bind:指定ip进行监听
    vim /opt/redis_cluster/redis_6379/conf/redis_6379.conf
    bind 10.0.0.181 127.0.0.1
    2)增加requirepass {password}
    requirepass 123456

    #验证方法一:登录后输入目录,
    [root@mariadb ~]# redis-cli -h db01
    db01:6379> KEYS *
    (error) NOAUTH Authentication required.
    db01:6379> AUTH 123456
    OK
    db01:6379> KEYS * 
     996) "K_1643"
     997) "K_1187"
     998) "K_1812"
     999) "K_1600"
    1000) "K_1680"
    1001) "K_1234"
    1002) "K_1961"
    1003) "K_1198"

    #验证方法二:登录后面直接接密码
    [root@mariadb ~]# redis-cli -h db01 -a 123456
    db01:6379> KEYS * 
     996) "K_1643"
     997) "K_1187"
     998) "K_1812"
     999) "K_1600"
    1000) "K_1680"
    1001) "K_1234"
    1002) "K_1961"
    1003) "K_1198"

架构

1、主从复制

- 备用服务器安装
    #打包主服务器的配置,拷贝到从服务器
    tar zcvf db01.tar.gz /opt/redis_cluster/
    scp db01.tar.gz 172.16.214.185:/tools/
    #解压,并执行make install 安装对应的命令
    tar zxf /tools/db01.tar.gz -C /opt/
    mv opt/* ./
    #创建数据目录
    mkdir -p /data/redis_cluster/redis_6379/
    #修改对应的配置文件信息 ,修改对应的主机地址
    bind 10.0.0.185
    #启动对应的服务
    redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf
- 进行复制、同步
    1、热备份
        redis-cli -h 10.0.0.185
        # 语法: SLAVEOF host port
        SLAVEOF 10.0.0.181 6379 
    2、直接写入配置文件
        slaveof 10.0.0.181 6379
    3、取消主从 #生命没有任何关联
        slaveof no one

- 主从同步流程
    1、从库发起同步请求
    2、主库收到请求后,执行bgsave保存当前内存里的数据到磁盘
    3、主库蒋持久化的数据发送给从库的数据目录
    4、从库收到主库的持久化数据后,先进行自己内存中的数据清楚
    5、从库将逐鹿发送过来的持久化文件加载到自己的内存里

- 局限性:
    1、执行主从复制之前,现将所有的数据都备份
    2、建议将主从复制写入到配置文件
    3、在业务低峰期做主从复制,
    4、拷贝数据是会占用带宽
    5、不能自动完成主从切换,需要人工接入

2、哨兵

- 主要功能
  #介绍
    Redis Sentinel 是一个分布式系统,Redis Sentinel为Redis提供高可用行.可以在没有认为敢于的情况下阻止某种类型的故障
  #主要任务
    1、监控
        Sentinel会不断的定期检查你的主服务器和从服务器是否运作正常
    2、提醒
        当被监控的某个Redis服务器出现问题是,Sentinel可以通过api想管理员或者其他应用程序发送通知
    3、自动故障迁移
        当一个主服务器不能正常公职是,Sentinel会开始第一次自动故障迁移操作,他会将失效主服务器的其中一个从服务器升级为新的主服务器。并让失效主服务器的其他从服务器改为复制新的主服务器,当客户端师徒连接失效的主服务器是,集群也会想客户端返回新的主服务器地址,是的集群可以使用新的主服务器代替失效服务器.
image.png
- 环境准备,
    准备1个主redis服务器,10.0.0.181 db01
    准备2个从redis服务器,10.0.0.185/186 db02/db03

- 角色 目录规划
    角色              ip          端口
   Master       10.0.0.181      6379
   Sentinel-01                  26379
   Master       10.0.0.185      6379
   Sentinel-02                  26379
    Master      10.0.0.186      6379
   Sentinel-03                  26379
- 添加目录 创建配置文件,
     DB01操作 
        mkdir -p /opt/redis_cluster/redis_26379/{conf,pid,logs}
        mkdir /data/redis_cluster/redis_26379
        vim /opt/redis_cluster/redis_26379/conf/redis_26379.conf
        bind 10.0.0.181
        port 26379
        daemonize yes
        logfile /opt/redis_cluster/redis_26379/logs/redis_26379.log
        dir /data/redis_cluster/redis_26379
        #master 主节点别名 主节点ip和端口 判断主节点失败,2个sentinel节点同意
        sentinel monitor mymaster 10.0.0.181 6379 2
        #选项指定了sentinel认为服务器已经断线所需的毫秒数
        sentinel down-after-milliseconds mymaster 3000
        #向新的主节点发起复制操作的从节点个数
        sentinel parallel-syncs mymaster 1
        #故障转移超时时间
        sentinel failover-timeout mymaster 18000
    DB02操作
        mkdir -p /opt/redis_cluster/redis_26379/{conf,pid,logs}
        mkdir /data/redis_cluster/redis_26379
        vim /opt/redis_cluster/redis_26379/conf/redis_26379.conf
        bind 10.0.0.185
        port 26379
        daemonize yes
        logfile /opt/redis_cluster/redis_26379/logs/redis_26379.log
        dir /data/redis_cluster/redis_26379
        #master 主节点别名 主节点ip和端口 判断主节点失败,2个sentinel节点同意
        sentinel monitor mymaster 10.0.0.181 6379 2
        #选项指定了sentinel认为服务器已经断线所需的毫秒数
        sentinel down-after-milliseconds mymaster 3000
        #向新的主节点发起复制操作的从节点个数
        sentinel parallel-syncs mymaster 1
        #故障转移超时时间
        sentinel failover-timeout mymaster 18000
    DB03操作
        mkdir -p /opt/redis_cluster/redis_26379/{conf,pid,logs}
        mkdir /data/redis_cluster/redis_26379
        vim /opt/redis_cluster/redis_26379/conf/redis_26379.conf
        bind 10.0.0.186
        port 26379
        daemonize yes
        logfile /opt/redis_cluster/redis_26379/logs/redis_26379.log
        dir /data/redis_cluster/redis_26379
        #master 主节点别名 主节点ip和端口 判断主节点失败,2个sentinel节点同意
        sentinel monitor mymaster 10.0.0.181 6379 2
        #选项指定了sentinel认为服务器已经断线所需的毫秒数
        sentinel down-after-milliseconds mymaster 3000
        #向新的主节点发起复制操作的从节点个数
        sentinel parallel-syncs mymaster 1
        #故障转移超时时间
        sentinel failover-timeout mymaster 18000


- 所有节点 启动redis 以及sentinel

    redis-server /opt/redis_cluster/redis_6379/conf/redis_6379.conf
    redis-sentinel /opt/redis_cluster/redis_26379/conf/redis_26379.conf
    查看状态
    [root@db01 redis_26379]# ps -ef | grep [r]edis
    root      80698      1  0 10:06 ?        00:00:00 redis-server 10.0.0.181:6379
    root      80756      1  0 10:10 ?        00:00:00 redis-sentinel 10.0.0.181:26379 [sentinel]

    #查询哨兵的服务的配置文件,已经变更
    [root@db01 conf]# cat /opt/redis_cluster/redis_26379/conf/redis_26379.conf
    bind 10.0.0.181
    port 26379
    daemonize yes
    logfile "/opt/redis_cluster/redis_26379/logs/redis_26379.log"
    dir "/data/redis_cluster/redis_26379"
    sentinel myid 22b4b5c975dec81d94d30eaf6b6c64935aef4647
    sentinel monitor mymaster 10.0.0.181 6379 2
    sentinel down-after-milliseconds mymaster 3000
    sentinel failover-timeout mymaster 18000
    # Generated by CONFIG REWRITE
    sentinel config-epoch mymaster 0
    sentinel leader-epoch mymaster 0
    sentinel known-slave mymaster 10.0.0.186 6379
    sentinel known-slave mymaster 10.0.0.185 6379
    sentinel known-sentinel mymaster 10.0.0.186 26379 382bda458ef7099e18f2dda0000da990df51d3ee
    sentinel known-sentinel mymaster 10.0.0.185 26379 c7cbb5c98a998e38bce3291c00428e8875ee8b27
    sentinel current-epoch 0

- 哨兵常用操作API
    #登录命令
        redis-cli -h db01 -p 26379 
    #Sentinel节点是一个特殊的redis节点,他们有自己的专属API
      Info Sentinel                                     #查询相关主节点、哨兵节点的信息
      Sentinel masters                                  #查询所有master信息
      Sentinel master                      #查询当前master组信息
      Sentinel slaves                      #查询当前master组对应的slave信息
      Sentinel sentinels                   #查询当前master组对应的sentinels信息
      Sentinel get-master-addr-by-name     #查询当前master节点对应的ip以及端口


- 模拟故障转移

    #关闭redis主节点的服务,哨兵进行自动切换,
    #查询从节点的日志 已经切换正常
       35636:X 29 Sep 15:05:35.298 # +sdown master mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:35.299 # +sdown sentinel 22b4b5c975dec81d94d30eaf6b6c64935aef4647 10.0.0.181 26379 @ mymaster    10.0.0.181 6379
       35636:X 29 Sep 15:05:35.371 # +odown master mymaster 10.0.0.181 6379 #quorum 2/2
       35636:X 29 Sep 15:05:35.371 # +new-epoch 1
       35636:X 29 Sep 15:05:35.371 # +try-failover master mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:35.372 # +vote-for-leader c7cbb5c98a998e38bce3291c00428e8875ee8b27 1
       35636:X 29 Sep 15:05:35.378 # 382bda458ef7099e18f2dda0000da990df51d3ee voted for c7cbb5c98a998e38bce3291c00428e8875ee8b27 1
       35636:X 29 Sep 15:05:35.473 # +elected-leader master mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:35.473 # +failover-state-select-slave master mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:35.565 # +selected-slave slave 10.0.0.186:6379 10.0.0.186 6379 @ mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:35.565 * +failover-state-send-slaveof-noone slave 10.0.0.186:6379 10.0.0.186 6379 @ mymaster 10.0.0.181    6379
       35636:X 29 Sep 15:05:35.656 * +failover-state-wait-promotion slave 10.0.0.186:6379 10.0.0.186 6379 @ mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:35.748 # +promoted-slave slave 10.0.0.186:6379 10.0.0.186 6379 @ mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:35.748 # +failover-state-reconf-slaves master mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:35.815 * +slave-reconf-sent slave 10.0.0.185:6379 10.0.0.185 6379 @ mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:36.376 * +slave-reconf-inprog slave 10.0.0.185:6379 10.0.0.185 6379 @ mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:36.502 # -odown master mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:37.450 * +slave-reconf-done slave 10.0.0.185:6379 10.0.0.185 6379 @ mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:37.506 # +failover-end master mymaster 10.0.0.181 6379
       35636:X 29 Sep 15:05:37.506 # +switch-master mymaster 10.0.0.181 6379 10.0.0.186 6379
       35636:X 29 Sep 15:05:37.506 * +slave slave 10.0.0.185:6379 10.0.0.185 6379 @ mymaster 10.0.0.186 6379
       35636:X 29 Sep 15:05:37.507 * +slave slave 10.0.0.181:6379 10.0.0.181 6379 @ mymaster 10.0.0.186 6379
       35636:X 29 Sep 15:05:40.525 # +sdown slave 10.0.0.181:6379 10.0.0.181 6379 @ mymaster 10.0.0.186 6379
    #在对应的哨兵查询目前的主节点
        redis-cli -h db02 -p 26379
        db02:26379> Sentinel get-master-addr-by-name mymaster
        1) "10.0.0.186"
        2) "6379"

    #恢复主节点,之前的主节点已经是新的主节点的从


- 权重设置 强制指定性能比较好的服务器为主

    Redis Sentinel存在多个节点是,如果想蒋指定的从节点晋升为主节点,可以将其他从吉尔碘的slavepriority配置为0,!!!但是需要注意failover后吗,蒋slave-priority调回原值。防止出现故障,无法切换


    1、查询命令
        CONFIG GET slave-priority
    2、设置命令
        CONFIG SET slave-priority 0
    3、主动切换:(在需要切换成主的从节点的机器 哨兵运行改命令,强制故障切换)
        sentinel failover mymaster


    - 操作过程:
        db02/db03操作
            redis-cli -h db02 CONFIG GET slave-priority
            1) "slave-priority"
            2) "100"
            redis-cli -h db02 CONFIG SET slave-priority 0
            OK
            redis-cli -h db02 CONFIG GET slave-priority
            1) "slave-priority"
            2) "0"

            redis-cli -h db03 CONFIG GET slave-priority
            1) "slave-priority"
            2) "100"
            redis-cli -h db03 CONFIG SET slave-priority 0
            OK
            redis-cli -h db03 CONFIG GET slave-priority
            1) "slave-priority"
            2) "0"

        db01操作
            redis-cli -h db01 -p 26379 Sentinel failover mymaster
            OK


        #查询现在的主节点:
            redis-cli -h db01 -p 26379 Sentinel get-master-addr-by-name mymaster
            1) "10.0.0.181"
            2) "6379"


        #修改db01和db02的slave-priority权重值为原值。

            redis-cli -h db02 CONFIG SET slave-priority 100
            redis-cli -h db02 CONFIG SET slave-priority 100

切换流程图


image.png

3、集群

-  介绍
    Redis Cluster 是redis的分布式解决方案,在3.0版本正式推出、
    当遇到单机、内存、并发、流量等瓶颈时 ,可以采用Cluster架构方案达到负载均衡木兰科
    Redis Cluster 之前的分布式方案有2中:
    1)客户端分区方案,有点分区逻辑可控,缺点是需要自己代码去处理数据路由
    2)代理方案,有点建华客户端分布式逻辑和升级维护便利,缺点家中架构部署和性能消耗
- 目录规划
    redis安装目录
    /opt/redis_cluster/redis_[port]/{conf,logs,pid}
    redis数据目录
    /data/redis_cluster/redis_[port]/redis_[port].rdb

集群拓扑图
image.png

手动搭建部署集群
1)部署第一台服务器上的2个集群节点
2)发送完成后修改其他主机的ip地址
3)ansible批量部署

实现命令:
DB01操作

#创建对应的目录
mkdir -p /opt/redis_cluster/redis_{6380,6381}/{conf,logs,pid}
mkdir -p /data/redis_cluster/redis_{6380,6381}
#编写配置文件
cat >/opt/redis_cluster/redis_6380/conf/redis_6380.conf <

DB02操作

find /opt/redis_cluster/redis_638* -type f -name "*.conf" | xargs sed -i "/bind/s#181#185#g"
mkdir -p /data/redis_cluster/redis_{6380,6381}

DB03操作:

find /opt/redis_cluster/redis_638* -type f -name "*.conf" | xargs sed -i "/bind/s#181#186#g"
mkdir -p /data/redis_cluster/redis_{6380,6381}

所有服务器启动对应的服务

redis-server /opt/redis_cluster/redis_6380/conf/redis_6380.conf
redis-server /opt/redis_cluster/redis_6381/conf/redis_6381.conf
  • 手动配置集群发现 任意节点执行
#添加集群发现
10.0.0.181:6380> CLUSTER MEET 10.0.0.181 6381
OK
#查询集群节点
CLUSTER NODES
a68f6869238d307f63d14d1c319ce4ff22228455 10.0.0.185:6380 master - 0 1601435619729 0 connected
9cbb441f5c95d3f4a79a95e451416203b5d91efc 10.0.0.186:6381 master - 0 1601435617706 4 connected
966b0c81209f90f49cacf33121739d19bead0f1d 10.0.0.185:6381 master - 0 1601435618713 3 connected
9f61bf0f2021832583c5c05448362ddad59adec5 10.0.0.181:6381 master - 0 1601435616701 5 connected
31ffed5fe6da5ccb2b96b9e67d92b8659dd703de 10.0.0.181:6380 myself,master - 0 0 1 connected
657ee92eea8040ce69c20afb0ed8070ba652cafa 10.0.0.186:6380 master - 0 1601435617204 2 connected
  • Redis Cluster通讯流程
    1)集群中每一个节点都会单独开辟一个TCP通道,用于节点之前的批次通信,通信端口在基础端口上加10000
    2)每个节点在固定周期内通过特定规则选择结构点发送ping消息
    3)接收到ping消息的节点用pong消息作为相应,汲取中每个节点通过一定规则挑选要通信的节点,每个节点可能知道全部节点,也可能仅知道部分节点,只要这些节点批次可以正常通信,最终他们回达成一致的桩体,当节点出现故障,新节点接入,主从角色变化等,它能够不断的ping/pong消息,从而达到同步目的
  • 槽位分配-主从配置
#查询槽位
10.0.0.181:6380> CLUSTER info
cluster_state:fail #没有槽位
cluster_slots_assigned:0
cluster_slots_ok:0
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:0
cluster_current_epoch:5
cluster_my_epoch:1
cluster_stats_messages_sent:2776
cluster_stats_messages_received:2776
#分配槽位
1)手动分配槽位
redis-cli -h db01 -p 6380 cluster addslots {0..5461}
redis-cli -h db02 -p 6380 cluster addslots {5462..10922}
redis-cli -h db03 -p 6380 cluster addslots {10923..16383}
2)工具
......
#配置主从
#查看节点、
[root@db01 scripts]# redis-cli -h db01 -p 6380 cluster nodes | awk '/6380/{print $1,$2}'
a68f6869238d307f63d14d1c319ce4ff22228455 10.0.0.185:6380
31ffed5fe6da5ccb2b96b9e67d92b8659dd703de 10.0.0.181:6380
657ee92eea8040ce69c20afb0ed8070ba652cafa 10.0.0.186:6380
#创建复制关系 
 redis-cli -h db01 -p 6381 cluster REPLICATE a68f6869238d307f63d14d1c319ce4ff22228455
OK
 redis-cli -h db02 -p 6381 cluster REPLICATE 657ee92eea8040ce69c20afb0ed8070ba652cafa
OK
redis-cli -h db03 -p 6381 cluster REPLICATE 657ee92eea8040ce69c20afb0ed8070ba652cafa
OK
#插入数据
db01:6381> set 1 11
(error) MOVED 9842 10.0.0.185:6380
redis-cli -h db02 -p 6380
db02:6380> keys *
(empty list or set)
db02:6380> set 1 111
OK
#加入-c 插入数据后,自动识别到目标节点.      
db01:6380> set 123 123
(error) MOVED 5970 10.0.0.185:6380 
[root@db01 ~]# redis-cli -h db01 -p 6380 -c
db01:6380> set 123 123
-> Redirected to slot [5970] located at 10.0.0.185:6380
OK
  • 故障转移
    关闭掉一台住的机器,自动转移到从.
    可以同时坏掉一台机器一个从服务 或者 3个主服务

4、集群构建工具

  • redos-trib.rb 采用Ruby实现的redis集群管理工具,内部通过Cluster相关命令帮我们简化集群创建、检查、槽迁移金额均衡等常见运维操作,使用前需要先安装ruby依赖环境
- 安装命令
yum makecache fast #更新缓存
yum install rubygems #安装ruby
gem sources --remove https://rubygems.org/ #溢出ruby源,
gem sources -a http://mirrors.aliyun.com/rubygems/ #添加ruby 阿里云源
gem update - system     #更新系统
gem install redis -v 3.2.9 #安装依赖 (报错查看文档 https://blog.csdn.net/weixin_30344995/article/details/95782570   yum update -y nss curl libcurl)
#我们可以停掉所有的节点,然后清空数据,恢复成一个全新的集群,所有机器执行命令
pkill redis
rm -rf /data/redis_cluster/redis_6380/*
rm -rf /data/redis_cluster/redis_6381/*
#全部清空之后启动所有的节点,所有机器执行
sh redis.sh start 6380
sh redis.sh start 6381
#db01执行创建集群命令
./redis-trib.rb create --replicas 1 10.0.0.181:6380 10.0.0.181:6381 10.0.0.185:6380 10.0.0.185:6381 10.0.0.186:6380 10.0.0.186:6381

#之后输入yes(注意  自动生成的集群,主从存在本机复制本机现象,需要调整主从关系)

redis-cli -h db02 -p 6381 cluster REPLICATE 657ee92eea8040ce69c20afb0ed8070ba652cafa
OK
redis-cli -h db03 -p 6381 cluster REPLICATE 657ee92eea8040ce69c20afb0ed8070ba652cafa
OK
# 检查集群完整性
./redis-trib.rb check 10.0.0.181:6380
>>> Performing Cluster Check (using node 10.0.0.181:6380)
M: d3add0da8168198cb47d28e98a233b1c9166e3ec 10.0.0.181:6380
 slots:0-5460 (5461 slots) master
1 additional replica(s)
S: e26989d9ff1d513aa361e74e217c47a4a85fd0d3 10.0.0.181:6381
 slots: (0 slots) slave
replicates 4b910222cc4a6b73a852044d1e3f00a8ff3b58a5
M: 4b910222cc4a6b73a852044d1e3f00a8ff3b58a5 10.0.0.185:6380
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 985f6b06a6b057fcf970b0793f60d5a66721cf62 10.0.0.185:6381
 slots: (0 slots) slave
replicates 7c10f584f9cae265c95b5d3e5149c4b88dca9ec9
M: 7c10f584f9cae265c95b5d3e5149c4b88dca9ec9 10.0.0.186:6380
 slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: eb858cba15f73853124d5f5d6e1d2c9c83c2fa1f 10.0.0.186:6381
slots: (0 slots) slave
replicates d3add0da8168198cb47d28e98a233b1c9166e3ec
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
# 检查集群负载情况
./redis-trib.rb rebalance 10.0.0.185:6380
>>> Performing Cluster Check (using node 10.0.0.185:6380)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
*** No rebalancing needed! All nodes are within the 2.0% threshold.

5、扩容收缩

- 生产环境中,不手动扩容.
- 工具扩容节点
   Redis集群的扩容操作可分为以下几个步骤
    1)准备新节点
    2)加入集群
    3)迁移槽和数据
    扩容流程图:
##我们在db01上创建2个新节点
mkdir -p /opt/redis_cluster/redis_{6390,6391}/{conf,logs,pid}
mkdir -p /data/redis_cluster/redis_{6390,6391}
cd /opt/redis_cluster/
cp redis_6380/conf/redis_6380.conf redis_6390/conf/redis_6390.conf
cp redis_6380/conf/redis_6380.conf redis_6391/conf/redis_6391.conf
sed -i 's#6380#6390#g' redis_6390/conf/redis_6390.conf
sed -i 's#6380#6391#g' redis_6391/conf/redis_6391.conf
#启动节点
redis-server /opt/redis_cluster/redis_6390/conf/redis_6390.conf
redis-server /opt/redis_cluster/redis_6391/conf/redis_6391.conf
#发现节点(手动)
redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.181 6390
redis-cli -c -h db01 -p 6380 cluster meet 10.0.0.181 6391
#工具发现节点
cd /opt/redis_cluster/redis/src/
./redis-trib.rb add-node 10.0.0.181:6390 10.0.0.181:6380
./redis-trib.rb add-node 10.0.0.181:6391 10.0.0.181:6380
#扩容、分配迁移槽
cd /opt/redis_cluster/redis/src/
./redis-trib.rb reshard 10.0.0.181:6380(注意 有交互,16384个槽   #4个节点 计算每个节点的槽位,输入)
打印出进群每个节点信息后,reshard命令需要确认迁移的槽数量,这里我们输入4096个:
How many slots do you want to move (from 1 to 16384)? 4096
输入6390的节点ID作为目标节点,也就是要扩容的节点,目标节点只能指定一个
What is the receiving node ID? xxxxxxxxx
之后输入源节点的ID,这里分别输入每个主节点的6380的ID最后输入done,或者直接输入all
Source node #1:all
image.png
image.png
###4096是: redis的总槽位是16384个  需要分配到每个节点的槽位 ##这里4个master节点,所以16384/4=4096
#第二项:是需要转移槽位到那个节点 
#第三项:是那些节点的槽位转移到新的节点,可以手动输入3个#Master节点的ID  然后输入done,或者直接输入all  所有的master节点
#第四项:输入yes开始转移
#迁移完成后命令会自动退出,这时候我们查看一下集群的状态
./redis-trib.rb rebalance 10.0.0.51:6380

###注意出现报错  可能是gem对应的redis版本问题,可以重新安装redis的版本为3.2.2
gem list
gem uninstall redis -v 4.2.2
gem install redis-3.2.2.gem 
  • 工具收缩节点

     流程说明
     1).首先需要确定下线节点是否有负责的槽,
     如果是,需要把槽迁移到其他节点,保证节点下线后整个集群槽节点映射的完整性.
     2).当下线节点不再负责槽或者本身是从节点时,
     就可以通知集群内其他节点忘记下线节点,当所有的节点忘记该节点后可以正常关闭.
     
     这里我们准备将刚才新添加的节点下线,也就是6390和6391
     收缩和扩容迁移的方向相反,6390变为源节点,其他节点变为目标节点,源节点把自己负责的4096个槽均匀的迁移到其他节点上,.
     由于redis-trib..rb reshard命令只能有一个目标节点,因此需要执行3次reshard命令,分别迁移1365,1365,1366个槽.
    
#操作命令:
cd /opt/redis_cluster/redis/src/
./redis-trib.rb reshard 10.0.0.181:6380
How many slots do you want to move (from 1 to 16384)? 1365  #(1365这个值是集群是4-1  剩余3个节点,要删除的节点的槽位数是4096除以3 的值)
#输入6380的id
#输入6390的id
done

- 忘记节点
#由于我们的集群是做了高可用的,所以当主节点下线的时候从节点也会顶上,所以最好我们先下线从节点,然后在下线主节点
cd /opt/redis_cluster/redis/src/
./redis-trib.rb del-node 10.0.0.51:6391 ID
./redis-trib.rb del-node 10.0.0.51:6390 ID

6、redis常用运维工具

  • 运维脚本 redis.sh

  • 数据导入导出工具
    刚切换到redis集群的时候肯定会面临数据导入的问题,所以这里推荐使用redis-migrate-tool工具来导入单节点数据到集群里

#安装工具
cd /opt/redis_cluster/
git clone https://github.com/vipshop/redis-migrate-tool.git
cd redis-migrate-tool/
autoreconf -fvi
./configure
make && make install
#创建配置文件  ##源节点  目标节点
cat > redis_6379_to_6380.conf <
  • 分析键值大小
#说明 :redis的内存使用太大键值太多,不知道哪些键值占用的容量比较大,而且在线分析会影响性能.
#安装工具
 yum install python-pip gcc python-devel 
cd /opt/
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
python2.7 setup.py install
#使用方法
cd /data/redis_cluster/redis_6380/
rdb -c memory redis_6380.rdb -f redis_6380.rdb.csv
#分析rdb并导出
awk -F ',' '{print $4,$2,$3,$1}' redis_6380.rdb.csv |sort  > 6380.txt

故障案列:

  • 常见故障案列
    redis动态调整内存故障
    config get maxmemory
    config set maxmemory

动态内存调整只能调整的比实际占用的大,不能调整的比实际占用的小,不然就会报错
动态调整的参数不会写入到配置文件里,配置文件里也看不到最大内存使用限制,及时重启,动态配置也会生效,只能通过config get maxmemory和config set maxmemory 0 (不限制内存使用)来恢复配置

redis默认启动不限制内存,线上环境,建议限制redis的最大使用内存为服务器的50%,
内存占用满之后,

  • 惰性删除
  • 随机删除
  • 什么都不做(默认)
maxmemory 
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes

你可能感兴趣的:(Redis基础&&集群)