• Redis 实战笔记


    Redis

    yum源安装

    yum install -y epel-release redis
    systemctl enable redis
    systemctl start redis
    systemctl status redis

    redis 简介

    Redis是一个开源的使用 C语言编写的 Key-value内存数据库
    读写性能强,支持多种数据类型
    把数据存储在内存中的高速缓存
    作者 Salvatore Sanfilippo
    # 中文文档
    http://www.redis.cn/documentation.html

    redis 特点

    速度快
    支持多种数据结构( string、list、hash、set、stored set)
    持久化
    主从复制(集群)
    支持过期时间
    支持事务
    消息订阅
    官方不支持 WINDOWS,但是有第三方版本

    Redis与 Memcache的对比



    对比测试


    Redis应用场景

    数据缓存
        提高访问性能,使用的方式与 memcache相同。
    会话缓存( Session Cache)
        保存Web会话信息
    排行榜/计数器
        Nginx+lua+Redis 计数器进行IP自动封禁
    消息队列
        构建实时消息系统,聊天,群聊。

    多实例

    复制redis.conf redis-server redis-cli 到不同的文件夹
    修改配置文件中的端口
    # 去除注释
    sed -ri '/^$|#/d' redis.conf
    # 后台启动
    [root@mysql-56 redis-6.0.9]# grep daemon redis.conf
    daemonize yes
    [root@mysql-56 redis-6.0.9]# ./src/redis-server redis.conf
    [root@mysql-56 redis-6.0.9]# ./src/redis-cli -p 6380
    127.0.0.1:6380>

    redis 源码安装

    #安装
    wget http://download.redis.io/releases/redis-3.2.6.tar.gz
    tar xzf redis-3.2.6.tar.gz
    cd redis-3.2.6
    make
    
    #运行
    src/redis-server
    #客户端
    src/redis-cli
    
    #查看路径
    rpm -ql redis 
    
    # 启动客户端端口
    redis-cli -p 6380


    配置文件

    主目录下 redis.conf  
    port 6380    # 端口
    daemonize yes                          # 后台运行
    pidfile /var/run/redis_6380.pid        #进程文件
    logfile "/data/redis6380/redis.log"    #日志文件
    appendonly yes        #日志开关
    dbfilename dump.rdb    # 持久化数据文件
    
    
    [root@mysql-56 redis-6.0.9]# ls /data/redis6380/
    redis.conf  redis.log  redis-server


    redis 保护模式

    一键部署
    [root@mysql-56 redis-6.0.9]# cat /usr/lib/systemd/system/redis.service
    [Unit]
    Description=Redis persistent key-value database
    After=network.target
    After=network-online.target
    Wants=network-online.target
    
    
    [Service]
    ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised systemd
    ExecStop=/usr/libexec/redis-shutdown
    Type=notify
    User=redis
    Group=redis
    RuntimeDirectory=redis
    RuntimeDirectoryMode=0755
    
    
    [Install]
    WantedBy=multi-user.target

    Bind 保护模式

    • Redis 3.2 新特性
        -解决访问安全
    • Bind
        -指定IP进行监听 bind 10.0.0.11
    • 禁止 protected-mode
        protected-mode yes/no
    • 增加 requirepass {password}
        requirepass 123456
    • 在redis-cli中使用
        auth {password}进行认证
    [root@mysql-56 redis-6.0.9]# grep prote redis.conf
    protected-mode yes
    requirepass 123456
    
    127.0.0.1:6380> SHUTDOWN
    not connected> exit
    127.0.0.1:6380> get foo
    (error) NOAUTH Authentication required.
    127.0.0.1:6380> auth 123456
    OK
    127.0.0.1:6380> get a
    "1"

    redis 数据

    获取当前配置
    CONFIG GET *
    变更运行配置
    CONFIG SET loglevel "notice"


    持久化

    • RDB持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot)
    • AOF持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。AOF文件中的命令全部以Redis协议的格式来保存,新命令会被追加到文件的末尾。Redis还可以在后台对AOF文件进行重写(rewrite),使得AOF文件的体积不会超出保存数据集状态所需的实际大小。
    • Redis还可以同时使用AOF持久化和RDB持久化。在这种情况下,当 Redis重启时,它会优先使用AOF文件来还原数据集,因为AOF文件保存的数据集通常比RDB文件所保存的数据集更完整。
    • 你甚至可以关闭持久化功能,让数据只在服务器运行时存在。

    持久化策略

    日志文件 appendonly yes/no
    save 900 1
    save 300 10
    save 60  10000
    分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改,即将数据写入硬盘。

    压缩

    decompression yes
    -指定存储至本地数据库时是否压缩数据,默认为yes,Redis 采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大

    同步

    appendfsync everysec
        - no:表示等操作系统进行数据缓存同步到磁盘,linux 约30秒(快)
        - always:表示每次更新操作后调用fsync()将数据写到磁盘(慢,安全)
        - everysec:表示每秒同步一次(折中,默认值)

    核心实战


    数据类型



    常规操作

    KEYS * 查看KEY支持通配符
    DEL    删除给定的一个或多个key
    EXISTS    检查是否存在
    EXPIRE    设定生存时间
    TTL        以秒为单位返回过期时间
    DUMP RESTORE        序例化与反序列化
    PEXIRE PTTL PERSIST    以毫秒为单位
    RENAME    变更KEY名
    SORT    键值排序,有非数字时报错
    TYPE    返回键所存储值的类型

    字符串


    SET name lewen
    Get name
    一个键最大能存储512MB
    Append    #将value追加到key原来的值的末尾
    INCRBY    #增加
    DECRBY    #减少
        DECRBY count 20    减去指定量
    Mget mset    #同时获取设置一个或多个键值对
    STRLEN    #返回字符串长度
    INCR DECR    #将值增或减1

    练习

    127.0.0.1:6380> set name lewen
    OK
    127.0.0.1:6380> get name
    "lewen"
    127.0.0.1:6380> type name
    string
    
    
    127.0.0.1:6380> APPEND name 123
    (integer) 8
    127.0.0.1:6380> get name
    "lewen123"
    
    
    127.0.0.1:6380> mset name fadewalk age 24
    OK
    127.0.0.1:6380> get name
    "fadewalk"
    127.0.0.1:6380> get age
    "24"
    
    
    127.0.0.1:6380> mget name age
    1) "fadewalk"
    2) "24"
    
    
    127.0.0.1:6380> STRLEN name
    (integer) 8
    127.0.0.1:6380> STRLEN age
    (integer) 2
    
    127.0.0.1:6380> INCR age
    (integer) 25
    127.0.0.1:6380> INCR age
    (integer) 26
    
    127.0.0.1:6380> DECR age
    (integer) 25
    127.0.0.1:6380> DECR age
    (integer) 24
    
    重复set 会覆盖掉前面的值
    
    127.0.0.1:6380> EXISTS name
    (integer) 1
    127.0.0.1:6380> INCRBY age
    (error) ERR wrong number of arguments for 'incrby' command
    127.0.0.1:6380> INCRBY age 100
    (integer) 124

    hash

    Redis hash 是一个键值对集合。
    Redis hash 是一个 string类型的field 和 value 的映射表
    hash 特别适合用于存储对象。
    每个hash可以存储2^32-1键值对

    HSET HGET    #设置返回单个值
    HMSET HMGET    #设置返回多个值
    Hmset user name quo sex male age 22

    HGETALL   #返回KEY的所有键值
    HEXSITS   #判断是否存在
    HLEN      #判断长度
    HKEYS    #获取所有字典
    HVALS    #获取所有值
    HDEL     #删除key中的一个或多个指定域
    127.0.0.1:6380> hset user:1 name lewen
    (integer) 1
    127.0.0.1:6380> TYPE user:1
    hash
    127.0.0.1:6380> hset user:1 set male
    (integer) 1
    
    127.0.0.1:6380> hgetall user:1
    1) "name"
    2) "lewen"
    3) "age"
    4) "24"
    5) "set"
    6) "male"
    127.0.0.1:6380> hget user:1 name
    "lewen"
    127.0.0.1:6380> hget user:1 age
    "24"
    127.0.0.1:6380> hmget user:1 name age
    1) "lewen"
    2) "24"
    
    删除
    127.0.0.1:6380> hdel user:1 name
    (integer) 1
    127.0.0.1:6380> hdel user:1 set
    (integer) 1
    127.0.0.1:6380> del user:1
    (integer) 1
    127.0.0.1:6380> keys *
    1) "age"
    2) "name"
    
    
    127.0.0.1:6380> hmset user name lewen age 24 sex male
    OK
    127.0.0.1:6380> HINCRBY user age 10
    (integer) 34
    127.0.0.1:6380> HINCRBY user age -5
    (integer) 29

    list

    Redis    列表是简单的字符串列表。
    按照插入顺序排序每个
    LIST可以存储2^32-1键值对

    LPUSH    #将一个或多个值插入到列表头部
    RPUSH    #将一个或多个值插入到列表尾部
    LPOP/RPOP    #移除表头/尾的元素
    LLEN      #返回列表长度
    LRANGE    #返回指定的元素
    LREM greet 2 morning    #删除前两个 morning
    LREM greet -1 morning   #删除后一个 morning
    LREM greet 0 hello     #删除所有 hello

    Lindex    #返回列表key中下标为 index的元素
    LSET key index value    #将列表key下标为 index的元素的值设置为value
    LINSERT    #插入数据位于某元素之前或之后。
    LINSERT key BEFORE|AFTER pivot value

    127.0.0.1:6380> lpush found gf yfd jy fc zs
    (integer) 5
    127.0.0.1:6380> type found
    list
    
    
    127.0.0.1:6380> lrange found 0 10
    1) "zs"
    2) "fc"
    3) "jy"
    4) "yfd"
    5) "gf"
    
    
    127.0.0.1:6380> lrange found 0 3
    1) "zs"
    2) "fc"
    3) "jy"
    4) "yfd"
    127.0.0.1:6380> lrange found 0 5
    1) "zs"
    2) "fc"
    3) "jy"
    4) "yfd"
    5) "gf"
    
    
    127.0.0.1:6380> lpush found wj
    (integer) 6
    127.0.0.1:6380> lrange found 0 5
    1) "wj"
    2) "zs"
    3) "fc"
    4) "jy"
    5) "yfd"
    6) "gf"
    
    
    127.0.0.1:6380> rpush found ha
    (integer) 7
    127.0.0.1:6380> lrange found 0 6
    1) "wj"
    2) "zs"
    3) "fc"
    4) "jy"
    5) "yfd"
    6) "gf"
    7) "ha"
    
    
    消费
    127.0.0.1:6380> rpop found
    "ha"
    127.0.0.1:6380> lrange found 0 6
    1) "wj"
    2) "zs"
    3) "fc"
    4) "jy"
    5) "yfd"
    6) "gf"
    127.0.0.1:6380> lpop found
    "wj"
    127.0.0.1:6380> lrange found 0 6
    1) "zs"
    2) "fc"
    3) "jy"
    4) "yfd"
    5) "gf"

    127.0.0.1:6380> rpush found bao1 bao2 bao3 bao4
    (integer) 9
    127.0.0.1:6380> lrange found 0 10
    1) "zs"
    2) "fc"
    3) "jy"
    4) "yfd"
    5) "gf"
    6) "bao1"
    7) "bao2"
    8) "bao3"
    9) "bao4"
    127.0.0.1:6380> lpop found
    "zs"
    127.0.0.1:6380> lpop found
    "fc"
    127.0.0.1:6380> lpop found
    "jy"
    127.0.0.1:6380> lpop found
    "yfd"
    127.0.0.1:6380> lpop found
    "gf"
    127.0.0.1:6380> lpop found
    "bao1"
    
    127.0.0.1:6380> lrange found 0 10
    1) "bao2"
    2) "bao3"
    3) "bao4"
    127.0.0.1:6380> LLEN found
    (integer) 3
    




    127.0.0.1:6380> rpush found bao1 bao2 bao3 bao4
    (integer) 7
    127.0.0.1:6380> lrange found 0 10
    1) "bao2"
    2) "bao3"
    3) "bao4"
    4) "bao1"
    5) "bao2"
    6) "bao3"
    7) "bao4"
    127.0.0.1:6380> lrem found 1 bao2
    (integer) 1
    127.0.0.1:6380> lrange found 0 10
    1) "bao3"
    2) "bao4"
    3) "bao1"
    4) "bao2"
    5) "bao3"
    6) "bao4"
    

    127.0.0.1:6380> lset found 0 baozi001
    OK
    127.0.0.1:6380> lrange found 0 10
    1) "baozi001"
    2) "bao4"
    3) "bao1"
    4) "bao2"
    5) "bao3"
    6) "bao4"
    


    127.0.0.1:6380> lindex found 0
    "baozi001"

    127.0.0.1:6380> linsert found after baozi001 baozi002
    (integer) 7
    127.0.0.1:6380> lrange found 0 10
    1) "baozi001"
    2) "baozi002"
    3) "bao4"
    4) "bao1"
    5) "bao2"
    6) "bao3"
    7) "bao4"

    redis 队列订阅

    生产消费模型


    消息模式

    • 发布消息通常有两种模式:队列模式( queuIng)和发布-订阅模式(publish- subscribe)。队列模式中, consumers可以同时从服务端读取消息,每个消息只被其中一个 consume读到。
    • 发布-订阅模式中消息被广播到所有的 consumer中, topic中的消息将被分发到组中的一个成员中。同一组中的 consumer可以在不同的程序中,也可以在不同的机器上。

    Redis 发布订阅

    • Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
    • Redis客户端可以订阅任意数量的频道。


    订阅发布实例

    SUBSCRIBE mq1    #客户端
    PUBLISH mq1 "Redis is a great caching technique"
    PSUBSCRIBE 订阅一个或多个符合给定模式的频道
    psubscribe news *tech*
    PUBLISH channel message
    将信息 message 发送到指定的频道 channel。返回值代表消费者数量
    pubsub channels    #显示订阅频道
        PUBSUB NUMSUB news.it    #打印各频道订阅者数量
    PUNSUBSCRIBE    #退订多个频道
    SUBSCRIBE       #订阅给定的一个或多个频道的信息。
    UNSUBSCRIBE     #退订频道

    127.0.0.1:6380> PUBLISH mq1 "redis is a great caching technique"
    (integer) 2
    127.0.0.1:6380>






    Redis 事务

    Redis 事务可以一次执行多个命令
    事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。
    事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
    原子性:事务中的命令要么全部被执行,要么全部都不执行。

    执行过程
    • 开始事务
    • 命令入队
    • 执行事务


    事务命令

    DISCARD
        取消事务,放弃执行事务块内的所有命合。
    EXEC
        执行所有事务块内的命令
    MULTI
        标记一个事务块的开始
    UNWATCH
        取消 WATCH命合对所有key的监视
    WATCH key [key....]
        -监视一个(或多个)key,如果在事务执行之前这个(或这些)key被其他命合所改动,那么事务捋被打断
























    数据备份

    [root@cs7 ~]# redis-cli
    127.0.0.1:6379> CONFIG GET dir  # 获取当前目录
    1) "dir"
    2) "/var/lib/redis"
    [root@cs7 ~]# ls /var/lib/redis/
    dump.rdb

    • Save备份(无持久化策略时),生成时在redis 当前目录中。
    • 恢复时只需将 dump.rdb 放入redis当前目录
       
    save 之后要关闭
    才会保存到文件

    备份恢复实例

    [root@mysql-56 redis6380]# egrep "port|daemon|dir|logfile|dbfilename" redis.conf
    port 6380
    daemonize yes
    logfile "./redis.log"
    dbfilename dump-6380.rdb
    dir /data/redis6380
    [root@mysql-56 redis6380]# tree
    .
    ├── appendonly.aof
    ├── dump-6380.rdb
    ├── redis.conf
    ├── redis.log
    └── redis-server


    [root@mysql-56 redis6380]# ./redis-server redis.conf
    [root@mysql-56 redis6380]# redis-cli -p 6380
    127.0.0.1:6380> KEYS *
    (empty list or set)
    127.0.0.1:6380> mset name lewen age 24
    OK
    127.0.0.1:6380> SHUTDOWN
    not connected> exit
    [root@mysql-56 redis6380]# ls
    appendonly.aof  dump-6380.rdb  redis.conf  redis.log  redis-server
    [root@mysql-56 redis6380]# mv dump-6380.rdb /tmp/
    [root@mysql-56 redis6380]# mv appendonly.aof /tmp/
    
    [root@mysql-56 redis6380]# ./redis-server redis.conf
    [root@mysql-56 redis6380]# redis-cli -p 6380
    127.0.0.1:6380> KEYS *
    (empty list or set)
    127.0.0.1:6380> SHUTDOWN
    not connected>
    [root@mysql-56 redis6380]# mv /tmp/dump-6380.rdb .
    [root@mysql-56 redis6380]# ls
    appendonly.aof  dump-6380.rdb  redis.conf  redis.log  redis-server
    [root@mysql-56 redis6380]# ./redis-server redis.conf
    [root@mysql-56 redis6380]# redis-cli -p 6380
    127.0.0.1:6380> KEYS *
    1) "age"
    2) "name"

    主从复制

    主从配置

    slaveof 192.168.1.1:6379
    slave-read-only     # 只读模式
    masterauth <password>        #主服务器设置密码后需要填写密码
    min-slaves-to-write <number of slaves>     #从服务器不少于,才允许写入
    min-slaves-max-lag <number of seconds>    #从服务器延迟不大于
    CONFIG set slave-read-only yes
    Config set masterauth root
    info replication
    SLAVEOF NO ONE    #升级至 MASTER


    127.0.0.1:6380> info replication
    # Replication
    role:master
    connected_slaves:2
    slave0:ip=127.0.0.1,port=6381,state=online,offset=140,lag=1
    slave1:ip=127.0.0.1,port=6382,state=online,offset=140,lag=1
    master_replid:8b3a113a7708b59ec6da191eab8ddfa3a5ec2b92
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:140
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:140
    


    127.0.0.1:6381> SLAVEOF 127.0.0.1 6380
    OK
    127.0.0.1:6382> SLAVEOF 127.0.0.1 6380
    OK
    
    127.0.0.1:6382> MGET name age
    1) "lewen"
    2) "24"
    127.0.0.1:6381> SLAVEOF no one


    基于 keepalived的自动故障切换






    Redis sentinel

    redis 哨兵
    实现主从复制master和slave 自动切换

    Redis sentinel

    ·Redis-Sentinel 是 Redis官方推荐的高可用性(HA)解决方案,当用Redis做 Master-slave的高可用方案时,假如 master宕机了,Redis本身(包括它的很多客户端)都没有实现自动进行主备切换,而Redis-sentinel 本身也是一个独立运行的进程,它能监控多个 master-slave 集群,发现 master宕机后能进行自动切换。

    功能

    监控( Monitoring):Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
    提醒( Notification):当被监控的某个Redis服务器出现问题时,Sentinel可以通过API向管理员或者其他应用程序发送通知。
    自动故障迁移( Automatic failover):当一个主服务器不能正常工时, Sentinel会开始一次自动故障迁移操作,它会将失效主服务器的其中一个从服务器升级为新的主服务器,并让失效主服务器的其他从服务器改为复制新的主服务器;当客户端试图连接失效的主服务器时,集群也会向客户端返回新主服务器的地址,使得集群可以使用新主服务器代替失效服务器。

    Sentinel 命令

    PING: 返回PONG
    SENTINEL masters:列出所有被监视的主服务器
    SENTINEL slaves <master name>
    SENTINEL get-master-addr-by-name<master name>:返回给定名字的主服务器的IP地址和端口号。
    SENTINEL reset <pattern>:重置所有名字和给定模式 pattern相匹配的主服务器。
    SENTINEL failover <master name>:当主服务器失效时,在不询问其他 Sentinel意见的情况下,强制开始一次自动故障迁移。

    查看配置文件

    配置


    cp src/redis-sentinel sentinel.conf 
    vim sentinel.conf
    port 26380
    dir "."
    sentinel monitor mcmaster 127.0.0.1 6381 1  # 主的个数,这里就写一个
    sentinel down-after-milliseconds mymaster 60000
    sentinel config-epoch mymaster O
    #启动
    ./redis-sentinel /sentinel.conf
    实操配置
    复制到哨兵文件到 /data/s1
    [root@mysql-56 s1]# cat sentinel.conf
    port 26379
    daemonize yes
    pidfile "/var/run/redis-sentinel.pid"
    logfile "./sentinel.log"
    dir "/data/s1/"
    sentinel myid 1c83d3230453094e2878f2f89dcd609ec601e380
    sentinel deny-scripts-reconfig yes
    sentinel monitor mymaster 127.0.0.1 6381 1
    sentinel down-after-milliseconds mymaster 10000
    sentinel config-epoch mymaster 1

    配置文件

    指定监控 master
    sentinel monitor mymaster 127.0.0.1 6379 2 {2表示多少个 sentinel同意}
    安全信息
    sentinel auth-pass mymaster luyx30
    超过15000毫秒后认为主机宕机
    sentinel down-after-milliseconds mymaster 15000
    ·当主从切换多久后认为主从切换失败
    sentinel failover-timeout mymaster 100000
    这两个配置后面的数量主从机需要一样, epoch为 master的版本
    sentinel leader-epoch mymaster 1
    sentinel config-epoch mymaster 1

    演示

    6380 挂了
    会自动的 6381 成为master
    当6380 恢复了以后,又可以加入成为slave
    如下:
    127.0.0.1:6380> info replication
    # Replication
    role:master
    connected_slaves:2
    slave0:ip=127.0.0.1,port=6381,state=online,offset=9326,lag=0
    slave1:ip=127.0.0.1,port=6382,state=online,offset=9326,lag=0
    master_replid:8b3a113a7708b59ec6da191eab8ddfa3a5ec2b92
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:9459
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:9459
    127.0.0.1:6380> SHUTDOWN
    not connected>
    
    
    [root@mysql-56 s1]# redis-cli -p 6381
    127.0.0.1:6381> info replication
    # Replication
    role:master
    connected_slaves:1
    slave0:ip=127.0.0.1,port=6382,state=online,offset=11106,lag=0
    master_replid:15dc060e31823a40c0e971733dc0add4c3e960f0
    master_replid2:8b3a113a7708b59ec6da191eab8ddfa3a5ec2b92
    master_repl_offset:11106
    second_repl_offset:10006
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:11106


    Redis cluster



    Redis集群

    Reds集群是一个可以在多个Redis节点之间进行数据共享的设施(installation)。
    Redis集群不支持那些需要同时处理多个键的Redis命合,因为执行这些命令需要在多个Redis节点之间移动数据,并且在高负载的情况下,这些命令将降低Redis集群的性能,并导致不可预测的行为
    Redis集群通过分区(partition)来提供一定程度的可用性(availability):即使集群中有一部分节点失效或者无法进行通讯,集群也可以继续处理命合请求。
    将数据自动切分(split)到多个节点的能力。
    当集群中的一部分节点失效或者无法进行通讯时,仍然可以继续处理命令请求的能力。


    前面是 主从复制的小集群


    Redis 集群数据共享

    • Redis集群使用数据分片(sharding)而非一致性哈希(consistency hashing)来实现:一个Redis集群包含16384个哈希槽( hash slot),数据库中的每个键都属于这16384个哈希槽的其中一个,集群使用公式CRC16(key)% 16384来计算键key属于哪个槽,其中CRC16(key)语句用于计算键key的CRC16校验和。
    • 节点A负责处理0号至5500号哈希槽。
    • 节点B负责处理5501号至11000号哈希槽。
    • 节点C负责处理11001号至16384号哈希槽

    集群的复制

    • 为了使得集群在一部分节点下线或者无法与集群的大多数(majority)节点进行通讯的情况下,仍然可以正常运作,Redis集群对节点使用了主从复制功能:集群中的每个节点都有1个至N个复制品(replicate),其中一个复制品为主节点(master),而其余的N-1个复制品为从节点(slave)。
    • 在之前列举的节点A、B、C的例子中,如果节点B下线了,那么集群将无法正常运行,因为集群找不到节点来处理501号至11000号的哈希槽。
    • 假如在创建集群的时候(或者至少在节点B下线之前),我们为主节点B添加了从节点B1,那么当主节点B下线的时候,集群就会捋B1设置为新的主节点,并让它代替下线的主节点B,继续处理5501号至11000号的哈希槽,这样集群就不会因为主节点B的下线而无法正常运作了。
    • 不过如果节点B和B1都下线的话,Redis集群还是会停止运作。






    运行机制

    所有的 redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
    节点的fail是通过集群中超过半数的 master节点检测失效时才生效
    客户端与redis节点直连,不需要中间 proxy层.客户端不需要连接集群所有节点连接集群中任何一个可用节点即可

    把所有的物理节点映射到[0~16383] slot上,cluster 负责维护 node slot key


    注意

    需要安装ruby支持
    yum install ruby rubygems -y
    gem install redis
    <如果gem卡住不动,使用国内镜像>
    gemsources--addhttps://gems.ruby-china.org/--remove
    https://rubygems.org/
    gem sources -
    [root@mysql-56 s1]# yum install ruby rubygems -y
    [root@mysql-56 s1]# gem install redis




    [root@mysql-56 s1]# gem sources -a https://mirrors.ustc.edu.cn/rubygems/
    https://mirrors.ustc.edu.cn/rubygems/ added to sources
    [root@mysql-56 s1]# gem sources --remove https://rubygems.org/
    https://rubygems.org/ removed from sources
    [root@mysql-56 s1]# gem sources -l
    *** CURRENT SOURCES ***
    https://mirrors.ustc.edu.cn/rubygems/



    配置文件中包含

    cluster-enabled yes
    cluster-config-file nodes.conf
    cluster-node-timeout 5000
    appendonly yes

    创建多个实例

    #!/bin/bash
    rm -rf /data/700*
    for no in {0..5}
    do
        mkdir /data/700$no
        cd /data/700$no
        cp -r /data/redis6380/* ./    
        sed -i "s/port 6379/port 700$no/g" redis.conf
        sed -i "s/daemonize no/daemonize yes/g" redis.conf
        sed -i "s#/var/log/redis/redis.log#redis.log#g" redis.conf
        # sed -i "s/dump.rdb/dump_700$no.rdb/g" redis.conf
        # sed -i "s/appendonly.aof/appendonly_700$no.aof/g" redis.conf
        echo "cluster-enabled yes" >> redis.conf
        echo "cluster-config-file nodes.conf" >> redis.conf
        echo "cluster-node-timeout 5000" >> redis.conf
        sed -i "s/appendonly no/appendonly yes/g" redis.conf
        sed -i "s/redis_6379.pid/redis_700$no.pid/g" redis.conf
        sed -i "/dir/d" redis.conf
        echo 'dir "./"' >>redis.conf
        
    done


    启动实例

    #!/bin/bash
    for i in `ss -lntp|grep 700|egrep 'pid=[0-9]{4}'|awk -F '=|,' '{print $3}'`;do kill -9 $i;done
    for no in {0..5}
    do
    
        cd /data/700$no
        ./redis-server ./redis.conf
    
    done

    创建集群

    /data/redis-trib.rb create --replicas 1
    127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003
    127.0.0.1:7004 127.0.0.1:7005
    给定 redis-trib.rb程序的命合是 create,这表示我们希望创建一个新的集群。
    选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点
    之后跟着的其他参数则是实例的地址列表,我们希望程序使用这些地址所指示的实例来创建新集群。

    # 新的创建集群方式
    /data/redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1

    集群客户端
    [root@txy redis-6.0.9]# redis-cli -c -p 7000
    重新分片
    ./redis-trib.rb reshard 127.0.0.1:7000
    [root@txy redis-6.0.9]# redis-cli -c -p 7000
    127.0.0.1:7000> set name lewf
    -> Redirected to slot [5798] located at 127.0.0.1:7001
    OK
    127.0.0.1:7001> set name lewfd
    OK
    127.0.0.1:7001> set name lewfd
    OK
    127.0.0.1:7001> get name
    "lewfd"

    集群管理

    集群状态
    redis-cli -p 7000 cluster nodes |grep master
    故障转移
    redis-cli -p 7002 debug segfault
    查看状态
    redis-cli -p 7000 cluster nodes|grep master

    增加新的节点

    ./redis-trib.rb add-node 127.0.0.1:7006 127.0.0.1:7000
    变成某实例的从
    redis 127.0.0.1:7006 > cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
    删除一个节点
    redis-trib del-node ip:port '<node-id>'
    删除 master节点之前首先要使用 reshard 移除 master的全部 slot,然后再删除当前节点

    状态说明

    • 集群最近一次向节点发送PING命合之后,过去了多长时间还没接到回复。
    • 节点最近一次返回PONG回复的时间。
    • 节点的配置纪元(configuration epoch):详细信息请参考Redis 集群规范。
    • 本节点的网络连接情况:例如 connected。
    • 节点目前包含的槽:例如 1270.0.1:7001 目前包含号码为5960至10921的哈希槽。


    面试常问


    集群
    哨兵
    持久化问题

    redis qps

    单实例
    qps每天11万次

    不要超过5万
    最大3万







  • 相关阅读:
    vue 使用sass 和less
    生命周期函数以及vue的全局注册
    vue-router的简单实现原理
    vue的三种传参方式
    配置router列表
    vue传参二
    Gym 101933E(状态压缩+记忆化搜索)
    Gym 101933 A(dp)
    Gym 101775H(dp)
    Gym 101775 D (思维)
  • 原文地址:https://www.cnblogs.com/wenyule/p/14093068.html
Copyright © 2020-2023  润新知