zoukankan      html  css  js  c++  java
  • & Redis学习记录

    Redis基础

    1 Redis简介

    2 Redis 安装及配置

    2.1 docker

    docker pull redis
    docker run -d --name redis -p 6379:6379 redis
    docker exec -it redis redis-cli

    2.2 Linux安装

    2.2.1 安装方法一:

    • 1.确保Linux已经安装gcc
    • 2.下载Redis
      wget http://download.redis.io/releases/redis-4.0.1.tar.gz
    • 3.解压
      tar -zxvf redis-4.0.1.tar.gz
    • 4.进入目录后编译
      cd redis-4.0.1
      make MALLOC=libc
    • 5.安装
      make PREFIX=/usr/local/redis install #指定安装目录为/usr/local/redis
    • 6.启动
      /usr/local/redis/bin/redis-server

    2.2.2 安装方法二:

    1.获取redis资源
      wget http://download.redis.io/releases/redis-4.0.8.tar.gz

    2.解压
      tar xzvf redis-4.0.8.tar.gz

    3.安装
      cd redis-4.0.8
      make
      cd src
      make install PREFIX=/usr/local/redis

    4.移动配置文件到安装目录下
      cd ../
      mkdir /usr/local/redis/etc
      mv redis.conf /usr/local/redis/etc

    5.配置redis为后台启动
      vi /usr/local/redis/etc/redis.conf //将daemonize no 改成daemonize yes

    6.将redis加入到开机启动
      vi /etc/rc.local //在里面添加内容:/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf (意思就是开机调用这段开启redis的命令)

    7.开启redis
      /usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf

    常用命令

    redis-server /usr/local/redis/etc/redis.conf //启动redis
      pkill redis //停止redis
      卸载redis:
        rm -rf /usr/local/redis //删除安装目录
        rm -rf /usr/bin/redis-* //删除所有redis相关命令脚本
        rm -rf /root/download/redis-4.0.4 //删除redis解压文件夹

    3 Redis 配置文件

    3.1 redis.conf 位置

    3.2 Unit 单位

    配置大小单位,开头定义了一些基本的度量单位,只支持bytes,不支持bit
    对大小写不敏感

    3.3 INCLUDES包含

    可以通过includes包含,redis.conf可以作为总闸,包含其他redisd的配置文件。

    3.4 GENERAL通用(通用标准化配置)

    3.4.1 Daemonize

    默认为no,修改为yes启用守护线程

    3.4.2 Pidfile

    进程管道文件/var/run/redis.conf

    3.4.3 port

    默认为6379

    3.4.4 Tcp-backlog

    tcp-backing 551
    设置tcp的backlog,backlog其实是一个连接队列,backlog队列总和=未完成三次握手队列+已经完成三次握手队列。
    在高并发环境下你需要一个高backlog值来避免慢客户端连接问题。注意linux内核会将这个值减小到/proc/sys/net/core/somaxconn的值,所以需要确认增大somaxconn和tcp_max_syn_backing两个值来达到想要的效果。

    3.4.6 bind

    端口绑定

    3.4.7 timeout

    0 表示不关闭,超时连接

    3.4.8 tcp-keepalive

    单位为秒,如果设置为0,则不会进行Keepalive检测,建议设置成60

    心跳机制!!!

    3.4.9 loglevel

    日志级别
    debug
    verbose
    notice
    warning 生产模式

    级别越高,日志越少

    3.4.10 logfile

    日志文件

    3.4.11 Syslog-enabled

    系统日志

    3.4.12 Syslog-ident

    指定syslog里的日志标志
    日志开头

    3.4.13 Syslog-facility

    指定syslog设备,值必须是USER或LOCAL0-LOCAL7
    Must be USER or between LOCAL0-LOCAL7.

    此处为local0

    3.4.14 databases

    默认16个库

    3.5 SNAPSHOTTING快照

    3.5.1 save

    RDB是整个内存的压缩过的Snapshot,RDB的数据结构,可以配置复合的快照触发条件,
    默认是
    1分钟内改了1万次,
    或5分钟内改了10次,
    或15分钟内改了1次


    如果想禁用RDB持久化的策略,只要不设置任何save指令,或者给save传入一个空字符串参数也可以

    3.5.2 stop-writes-on-bgsave-error

    如果配置成no,表示你不在乎数据不一致或者有其他的手段发现和控制

    3.5.3 rdbcompression


    rdbcompression:对于存储到磁盘中的快照,可以设置是否进行压缩存储。如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,可以设置为关闭此功能

    3.5.4 rdbchecksum

    rdbchecksum:在存储快照后,还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能

    3.5.5 dbfilename

    dump.rdb

    3.5.6 dir

    备份目录
    config get dir 可以得到

    3.6 REPLICATION复制

    3.7 SECURITY安全

    requirepass 表示redis密码

    设置redis密码之后

    操作redis 之前需要输入 auth 密码

    3.8 LIMITS限制

    3.8.1 Maxclients

    最大连接数
    默认10000

    3.8.2 Maxmemory

    最大内存

    3.8.3 Maxmemory-policy及LRU算法

    缓存过期策略

    什么是缓存过期策略?

    MAXMEMORY POLICY: how Redis will select what to remove when maxmemory
    is reached. You can select among five behaviors:

    volatile-lru -> remove the key with an expire set using an LRU algorithm
    allkeys-lru -> remove any key according to the LRU algorithm
    volatile-random -> remove a random key with an expire set
    allkeys-random -> remove a random key, any key
    volatile-ttl -> remove the key with the nearest expire time (minor TTL)
    noeviction -> don't expire at all, just return an error on write operations

    默认缓存过期策略为永不过期

    LRU是什么
    LRU是Least Recently Used的缩写,即最近最少使用。
    LRU是Least Recently Used的缩写,即最近最少使用。
    LRU是Least Recently Used的缩写,即最近最少使用。
    LRU是Least Recently Used的缩写,即最近最少使用。
    LRU是Least Recently Used的缩写,即最近最少使用。

    解释

    • 当最大的内存值达到时,对redis而言,你可以从以下五种缓存过期策略中任选其一
    • volatile-lru
      • 使用LRU算法移除key,只对设置了过期时间的键
    • allkeys-lru
      • 使用LRU算法移除key
    • volatile-random
      • 在过期集合中移除随机的key,只对设置了过期时间的键
    • allkeys-random
      • 移除随机的key
    • volatile-ttl
      • 移除那些TTL值最小的key,即那些最近要过期的key
    • noeviction
      • 永不过期,不进行移除。针对写操作,只是返回错误信息

    3.8.4 Maxmemory-samples

    设置样本数量,LRU算法和最小TTL算法都并非是精确的算法,而是估算值,所以你可以设置样本的大小
    redis默认会检查这么多个key并选择其中LRU的那个

    3.9 APPEND ONLY MODE 追加

    3.9.1 appendonly

    是否开启aof

    3.9.2 appendfilename

    aof文件名称

    3.9.3 Appendfsync


    Everysec为默认

    • Always:
      • 同步持久化 每次发生数据变更会被立即记录到磁盘 性能较差但数据完整性比较好
    • Everysec:
      • 出厂默认推荐 异步操作,每秒记录 如果一秒内宕机,有数据丢失
    • no:
      • 不同步

    3.9.4 No-appendfsync-on-rewrite

    重写时是否可以运用Appendfsync,用默认no即可,保证数据安全性。

    3.9.5 Auto-aof-rewrite-min-size:设置重写的基准值

    设置重写的基准值 单位百分比
    它是设置aof rewrite触发时机的一个参数,当当前的aof文件大小超过上一次rewrite后aof文件的百分比后触发rewrite。

    3.9.6 Auto-aof-rewrite-percentage:设置重写的基准值

    设置重写的基准值

    aof文件重写最小的文件大小,即最开始aof文件必须要达到这个文件时才触发,后面的每次重写就不会根据这个变量了(根据上一次重写完成之后的大小).此变量仅初始化启动redis有效.如果是redis恢复时,则lastSize等于初始aof文件大小.


    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    此时表示
    Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64MB时触发

    3.10 常见配置总结redis.conf

    1. Redis默认不是以守护进程的方式运行,可以通过该配置项进行修改,使用yes启动守护进程
      1. daemonize no
    2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
      1. pidfile /var/run/redis.pid
    3. 指定Redis监听端口,默认端口为6379,作者在自己的一篇博文中解释了为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字
      1. port 6379
    4. 绑定的主机地址
      1. bind 127.0.0.1
    5. 当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
      1. timeout 300
    6. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
      1. loglevel verbose
    7. 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null
      1. logfile stdout
    8. 设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id
      1. databases 16
    9. 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合

    save <seconds> <changes>

    Redis默认配置文件中提供了三个条件:

    save 900 1

    save 300 10

    save 60 10000

    分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。

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

    rdbcompression yes

    1. 指定本地数据库文件名,默认值为dump.rdb

    dbfilename dump.rdb

    1. 指定本地数据库存放目录

    dir ./

    1. 设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步

    slaveof <masterip> <masterport>

    1. 当master服务设置了密码保护时,slav服务连接master的密码

    masterauth <master-password>

    1. 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭

    requirepass foobared

    1. 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息

    maxclients 128

    1. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区

    maxmemory <bytes>

    1. 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no

    appendonly no

    1. 指定更新日志文件名,默认为appendonly.aof

    appendfilename appendonly.aof

    1. 指定更新日志条件,共有3个可选值:

    no:表示等操作系统进行数据缓存同步到磁盘(快)

    always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)

    everysec:表示每秒同步一次(折衷,默认值)

    appendfsync everysec

    1. 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)

    vm-enabled no

    1. 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享

    vm-swap-file /tmp/redis.swap

    1. 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0

    vm-max-memory 0

    1. Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值

    vm-page-size 32

    1. 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。

    vm-pages 134217728

    1. 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4

    vm-max-threads 4

    1. 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启

    glueoutputbuf yes

    1. 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法

    hash-max-zipmap-entries 64

    hash-max-zipmap-value 512

    1. 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)

    activerehashing yes

    1. 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件

    include /path/to/local.conf

    4 Redis常用命令及五大数据类型

    Redis五种数据类型:string、hash、list、set、zset

    3.1 公用命令

    • DEL key
    • DUMP key:序列化给定key,返回被序列化的值
    • EXISTS key:检查key是否存在
    • EXPIRE key second:为key设定过期时间
    • TTL key:返回key剩余时间
    • PERSIST key:移除key的过期时间,key将持久保存
    • KEY pattern:查询所有符号给定模式的key
    • RANDOM key:随机返回一个key
    • RANAME key newkey:修改key的名称
    • MOVE key db:移动key至指定数据库中
    • TYPE key:返回key所储存的值的类型

    EXPIRE key second的使用场景:
    1、限时的优惠活动
    2、网站数据缓存
    3、手机验证码
    4、限制网站访客频率

    3.2 key的命名建议

    key不要太长,尽量不要超过1024字节。不仅消耗内存,也会降低查找的效率
    key不要太短,太短可读性会降低在一个项目中,
    key最好使用统一的命名模式,如user:123:password
    key区分大小写

    使用“:”冒号来体现层次。例如:set intern:user:user_code 123456  得到形式如下:

    3.3 string

    5 Redis持久化

    5.1 RDB

    5.1.1 是什么

    在指定时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复是将快照文件直接读到内存里。

    Redis会单独创建(Fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能。
    如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。

    Rdb 保存的是dump.rdb文件
    Rdb 保存的是dump.rdb文件
    Rdb 保存的是dump.rdb文件
    Rdb 保存的是dump.rdb文件
    Rdb 保存的是dump.rdb文件

    5.1.2 Fork

    Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等)
    数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程

    5.1.2 配置位置

    5.1.3 如何触发RDB快照

    1. 配置文件中默认的快照配置
      冷拷贝后使用(冷拷贝表示将配置文件从主机拷贝到备机上)

      可以cp dump.rdb dump_new.rdb
    2. 命令save或者是bgsave
      Save:save时只管保存,其它不管,全部阻塞
      BGSAVE:Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。可以通过lastsave命令获取最后一次成功执行快照的时间

    3.执行flushall命令,也会产生dump.rdb文件,但里面是空的,无意义

    5.1.4 如何恢复

    将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可

    CONFIG GET dir获取目录

    5.1.5 RDB优势与劣势

    • 优势
      • 适合大规模的数据恢复
      • 对数据完整性和一致性要求不高
    • 劣势
      • 在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改
      • Fork的时候,内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑

    5.1.6 总结

    5.2 AOF(Append Only File)

    5.2.1 是什么

    以日志的形式来记录每个写操作,将执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作

    默认 Aof保存的是appendonly.aof文件

    5.2.2 配置位置

    5.2.3 AOF启动/修复/恢复

    • 正常恢复
      • 修改配置文件:修改默认的appendonly no,改为yes
      • 将有数据的aof文件复制一份保存到对应目录(config get dir)
      • 恢复:重启redis然后重新加载
    • 异常恢复
      • 修改默认的appendonly no,改为yes
      • 备份被写坏的AOF文件
      • Redis-check-aof --fix进行修复
      • 恢复:重启redis然后重新加载

    5.2.4 Rewrite

    aof文件重写

    • 是什么
      • AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集.可以使用命令bgrewriteaof
    • 重写原理
      • AOF文件持续增长而过大时,会fork出一条新进程来将文件重写(也是先写临时文件最后再rename),遍历新进程的内存中数据,每条记录有一条的Set语句。重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似
    • 触发机制
      • Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64MB时触发

    5.2.5 aof优势与劣势

    • 优势
      • 每修改同步:appendfsync always   同步持久化 每次发生数据变更会被立即记录到磁盘  性能较差但数据完整性比较好
      • 每秒同步:appendfsync everysec    异步操作,每秒记录   如果一秒内宕机,有数据丢失
      • 不同步:appendfsync no   从不同步
    • 劣势
      • 相同数据集的数据而言aof文件要远大于rdb文件,恢复速度慢于rdb
      • Aof运行效率要慢于rdb,每秒同步策略效率较好,不同步效率和rdb相同

    5.2.6 总结

    6 Redis事务

    可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞

    一个队列中,一次性、顺序性、排他性的执行一系列命令

    6.1 事务有关命令

    6.1.1 正常执行

    6.1.2 放弃事务

    6.1.3 全体连坐

    将redis清空之后flushall


    编译出错 全体回滚

    6.1.4 冤头债主


    运行时出错 只回滚出错的那条

    6.1.5 watch监控

    • 初始化信用卡可用额度100和欠额0
      • 在同一个事务中 将可用额度-30 欠额+30
    • 无加塞篡改
      • 先监控再开启multi,保证两笔金额变动在同一个事务内
    • 有加塞篡改
      • 监控了key,如果key被修改了,后面一个事务的执行失效
    • unwatch
    • 一旦执行了unwatchexec之前加的监控锁都会被取消掉了
    • watch总结
      • Watch指令,类似乐观锁,事务提交时,如果Key的值已被别的客户端改变,比如某个list已被别的客户端push/pop过了,整个事务队列都不会被执行
      • 通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,EXEC命令执行的事务都将被放弃,同时返回Nullmulti-bulk应答以通知调用者事务执行失败

    6.2 事务3阶段

    • 开启:以MULTI开始一个事务
    • 入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面
    • 执行:由EXEC命令触发事务

    6.3 事务3特性

    • 单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
    • 没有隔离级别的概念:队列中的命令没有提交之前都不会实际的被执行,因为事务提交前任何指令都不会被实际执行,也就不存在”事务内的查询要看到事务里的更新,在事务外查询不能看到”这个让人万分头痛的问题
    • 不保证原子性:redis同一个事务中如果有一条命令执行失败,其后的命令仍然会被执行,没有回滚

    7 Redis发布订阅

    8 Redis的复制(Master/Slave)

    8.1 是什么

    行话:也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主

    • 作用
      • 读写分离
      • 容灾恢复
    • 主从复制缺点
      • 由于所有的写操作都是先在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使这个问题更加严重。

    8.2 具体配置

      1. 配从(库)不配主(库)
      1. 从库配置:slaveof 主库IP 主库端口
      • 每次与master断开之后,都需要重新连接,除非你配置进redis.conf文件
      • Info replication
      1. 修改配置文件细节
      • daemonize
      • logfile
      1. 常用3招
      • 一主二仆
      • 薪火相传
      • 反客为主
      1. 服务器规划
      • 192.168.136.128 master
      • 192.168.136.130 slave
      • 192.168.136.129 slave

    8.3 一主二仆

    8.3.1 配置演示

    1. 修改完配置文件(daemonize+logfile)之后
      分别启动3台服务器的redis 并查看当前redis状态 info replication
    2. 用slaveof命令设置一个master 两个slave
      slaveof <masterip> <masterport>
      slaveof masterIP masterPORT

    3. 查看当前状态信息
      1. 日志
        192.168.136.128 master 主服务器

        192.168.136.130 slave 备服务器

        192.168.136.129 slave 备服务器
        同130服务器
      2. info replication

    8.3.2 问题演示

    8.3.2.1 切入点问题:slave1、slave2是从头开始复制还是从切入点开始复制?

    比如从k4进来,那之前的123是否也可以复制
    问题描述

    先将master设置3个键
    set k1 v1
    set k2 v2
    set k3 v3
    然后此时再将两个slave->slaveof到master
    然后再添加master一个键k4
    set k4 v4
    此时 slave1 slave2 能取到k4的值

    问 之前的 k1 k2 k3能不能取到?

    可以 当slave与master建立关联之后 所有的键值都会复制一份

    8.3.2.2 从机是否可以写?set可否?


    不可以 只有master可以写!

    8.3.2.3 主机shutdown后情况如何?从机是上位还是原地待命


    原地待命

    8.3.2.4 主机又回来了后,主机新增记录,从机还能否顺利复制?

    可以顺利复制

    8.3.2.5 其中一台从机down后情况如何?依照原有它能跟上大部队吗?


    从机down掉 再次上线恢复之后 不能直接连上原来的master(丛机会自己变为master) 需要重新执行slaveof命令

    8.4 薪火相传

    上一个Slave可以是下一个slave的Master,Slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了链条中下一个的master,可以有效减轻master的写压力

    中途变更转向:会清除之前的数据,重新建立拷贝最新的

    命令:Slaveof 新主库IP 新主库端口

    8.5 反客为主

    192.168.136.128 master
    192.168.136.130 slave
    192.168.136.129 slave
    当128:master down掉之后
    此时130 129会原地待命 都是slave
    我们手动的将130变成 master

    命令 slaveof no one

    8.6 复制的原理

    • Slave启动成功连接到master后会发送一个sync命令
    • Master接到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,以完成一次完全同步
    • 全量复制:而slave服务在接收到数据库文件数据后,将其存盘并加载到内存中。
    • 增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步
    • 但是只要是重新连接master,一次完全同步(全量复制)将被自动执行

    8.7 哨兵模式(sentinel)

    反客为主的自动版,能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库

    8.7.1 结构调整及整体规划

    调整结构
    192.168.136.128 master
    192.168.136.130 slave
    192.168.136.129 slave

    配置1个哨兵和1主2从的Redis服务器来演示这个过程。

    服务类型是否是主服务器IP地址端口
    Redis 192.168.136.128 6379
    Redis 192.168.136.130 6379
    Redis 192.168.136.129 6379
    Sentinel - 192.168.136.128 26379

    8.7.2 sentinel.conf

    自定义的/etc 目录下新建sentinel.conf文件,名字绝不能错

    sentinel.conf文件内容
    prot 26379
    sentinel monitor 被监控数据库名字(自己起名字) 127.0.0.1 6379 1
    上面最后一个数字1,表示主机挂掉后salve投票看让谁接替成为主机,得票数多少后成为主机

    8.7.3 启动哨兵

    ./redis-sentinel /usr/local/redis/etc/sentinel.conf

    8.7.4 将master SHUTDOWN

    130的redis自动转为master
    查看sentinel日志 投票新选

    8.7.5 如果之前的master重启回来,会不会双master冲突?


    重启之前的master 之后 其自动变为slave

    8.8 多哨兵模式

    8.8.1 整体规划

    配置3个哨兵和1主2从的Redis服务器来演示这个过程。

    服务类型是否是主服务器IP地址端口
    Redis 192.168.136.128 6379
    Redis 192.168.136.130 6379
    Redis 192.168.136.129 6379
    Sentinel - 192.168.136.128 26379
    Sentinel - 192.168.136.130 26379
    Sentinel - 192.168.136.129 26379

    8.8.2 修改redis主从配置文件

    首先配置Redis的主从服务器,修改redis.conf文件如下

    # 使得Redis服务器可以跨网络访问
    bind 0.0.0.0
    # 设置密码
    requirepass 123456
    # 指定主服务器,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
    slaveof 192.168.136.128 6379
    # 主服务器密码,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
    masterauth 123456
    

    上述内容主要是配置Redis服务器,从服务器比主服务器多一个slaveof的配置和密码。

    8.8.3 修改redis主从配置文件

    配置3个哨兵,每个哨兵的配置都是一样的。在Redis安装目录下有一个sentinel.conf文件,copy一份进行修改

    # 端口号
    prot 26379
    # 后台启动
    daemonize yes
    # 日志文件
    logfile /usr/local/redis/bin/sentinel.log
    # 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.136.128代表监控的主服务器,6379代表端口,2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
    sentinel monitor mymaster 192.168.136.128 6379 2
    # sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
    # sentinel auth-pass <master-name> <password>
    sentinel auth-pass mymaster 123456
    

    8.8.4 启动redis和哨兵

    通过下面的命令启动服务器和哨兵

    # 启动Redis服务器进程
    ./redis-server ../redis.conf
    # 启动哨兵进程
    ./redis-sentinel ../sentinel.conf
    

    注意启动的顺序。首先是主机(192.168.136.128)的Redis服务进程,然后启动从机的服务进程,最后启动3个哨兵的服务进程。

    8.8.5 测试

    8.8.6 Jedis使用哨兵模式

    
    /**
     * 测试Redis哨兵模式
     */public class TestSentinels {
        @SuppressWarnings("resource")
        @Test
        public void testSentinel() {
            JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
            jedisPoolConfig.setMaxTotal(10);
            jedisPoolConfig.setMaxIdle(5);
            jedisPoolConfig.setMinIdle(5);
            // 哨兵信息
            Set<String> sentinels = new HashSet<>(Arrays.asList("192.168.11.128:26379",
                    "192.168.11.129:26379","192.168.11.130:26379"));
            // 创建连接池
            JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels,jedisPoolConfig,"123456");
            // 获取客户端
            Jedis jedis = pool.getResource();
            // 执行两个命令
            jedis.set("mykey", "myvalue");
            String value = jedis.get("mykey");
            System.out.println(value);
        }}
    

    上面是通过Jedis进行使用的,同样也可以使用Spring进行配置RedisTemplate使用。

    
            <bean >
                <!-- 最大空闲数 -->
                <property name="maxIdle" value="50"></property>
                <!-- 最大连接数 -->
                <property name="maxTotal" value="100"></property>
                <!-- 最大等待时间 -->
                <property name="maxWaitMillis" value="20000"></property>
            </bean>
            
            <bean >
                <constructor-arg name="poolConfig" ref="poolConfig"></constructor-arg>
                <constructor-arg name="sentinelConfig" ref="sentinelConfig"></constructor-arg>
                <property name="password" value="123456"></property>
            </bean>
            
            <!-- JDK序列化器 -->
            <bean ></bean>
            
            <!-- String序列化器 -->
            <bean ></bean>
            
            <bean >
                <property name="connectionFactory" ref="connectionFactory"></property>
                <property name="keySerializer" ref="stringRedisSerializer"></property>
                <property name="defaultSerializer" ref="stringRedisSerializer"></property>
                <property name="valueSerializer" ref="jdkSerializationRedisSerializer"></property>
            </bean>
            
            <!-- 哨兵配置 -->
            <bean >
                <!-- 服务名称 -->
                <property name="master">
                    <bean >
                        <property name="name" value="mymaster"></property>
                    </bean>
                </property>
                <!-- 哨兵服务IP和端口 -->
                <property name="sentinels">
                    <set>
                        <bean >
                            <constructor-arg name="host" value="192.168.11.128"></constructor-arg>
                            <constructor-arg name="port" value="26379"></constructor-arg>
                        </bean>
                        <bean >
                            <constructor-arg name="host" value="192.168.11.129"></constructor-arg>
                            <constructor-arg name="port" value="26379"></constructor-arg>
                        </bean>
                        <bean >
                            <constructor-arg name="host" value="192.168.11.130"></constructor-arg>
                            <constructor-arg name="port" value="26379"></constructor-arg>
                        </bean>
                    </set>
                </property>
            </bean>
    

    9 Redis 集群(redis3 or redis4)

    Redis 集群实现了对Redis的水平扩容,即启动N个redis节点,将整个数据库分布存储在这N个节点中,每个节点存储总数据的1/N。

    Redis 集群通过分区(partition)来提供一定程度的可用性(availability): 即使集群中有一部分节点失效或者无法进行通讯, 集群也可以继续处理命令请求。

    9.1 规划

    服务类型是否是主服务器IP地址端口
    Redis - 192.168.136.128 6379
    Redis - 192.168.136.130 6379
    Redis - 192.168.136.129 6379
    Redis - 192.168.136.131 6379
    Redis - 192.168.136.132 6379
    Redis - 192.168.136.133 6379

    192.168.136.128 安装ruby

    9.2 任选一台机器安装ruby

    • 1.能上网:
      • 执行yum install ruby
      • 执行yum install rubygems
    • 2.不能上网:
      • cd  /run/media/root/CentOS 7 x86_64/Packages(路径跟centos6不同)  获取下图rpm包
      • 拷贝到/opt/rpmruby/目录下,并cd到此目录
      • 执行:rpm -Uvh *.rpm --nodeps --force
      • 按照依赖安装各个rpm包
      • 拷贝redis-3.2.0.gem到/opt目录
      • 在opt目录下执行  gem install --local redis-3.2.0.gem

    9.3 修改redis配置文件

    • cluster-enabled yes    打开集群模式
    • cluster-config-file  nodes-端口号.conf  设定节点配置文件名
    • cluster-node-timeout 15000   设定节点失联时间,超过该时间(毫秒),集群自动进行主从切换

    9.4 合体

    • 将6个实例全部启动,nodes-端口号.conf文件都生成正常
    • 合体
      • 进入到 cd  /opt/redis-3.2.5/src
      • 执行 ./redis-trib.rb create --replicas 1 192.168.136.128:6379 192.168.136.130:6379 192.168.136.129:6379 192.168.136.131:6379 192.168.136.132:6379 192.168.136.133:6379
      • 注意: IP地址修改为当前服务器的地址,端口号为每个Redis实例对应的端口号.


    此处表示3个master为
    192.168.136.128:6379
    192.168.136.130:6379
    192.168.136.129:6379

    Adding replica 192.168.136.131:6379 是 192.168.136.128:6379 的从服务器
    Adding replica 192.168.136.132:6379 是 192.168.136.130:6379 的从服务器
    Adding replica 192.168.136.133:6379 是 192.168.136.129:6379 的从服务器


    此处表示
    192.168.136.128:6379master插槽为0-5460
    192.168.136.130:6379master插槽为5461-10922
    192.168.136.129:6379master插槽为10923-16383

    9.5 集群操作

    9.5.1 以集群的方式进入客户端

    redis-cli  -c  -p  端口号
    -c 表示cluster

    9.5.2 cluster nodes

    通过cluster nodes 命令查看集群信息

    128为master 128的slave为131 按照ID的尾数进行观察

    9.5.3 redis cluster 如何分配这六个节点

    • 一个集群至少要有三个主节点。
      • 选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点。
      • 分配原则尽量保证每个主数据库运行在不同的IP地址,每个从库和主库不在一个IP地址上。
    • 什么是slots
      • 一个 Redis 集群包含 16384 个插槽(hash slot), 数据库中的每个键都属于这 16384 个插槽的其中一个, 集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽, 其中 CRC16(key) 语句用于计算键 key 的 CRC16 校验和 。
      • 集群中的每个节点负责处理一部分插槽。 举个例子, 如果一个集群可以有主节点,
      • 其中:
      • 节点 A 负责处理 0 号至 5500 号插槽。
      • 节点 B 负责处理 5501 号至 11000 号插槽。
      • 节点 C 负责处理 11001 号至 16383 号插槽

    9.5.4 集群操作数据

    • 在redis-cli每次录入、查询键值,redis都会计算出该key应该送往的插槽,如果不是该客户端对应服务器的插槽,redis会报错,并告知应前往的redis实例地址和端口.
    • redis-cli客户端提供了 –c 参数实现自动重定向。
      • 如 redis-cli  -c –p 6379 登入后,再录入、查询键值对可以自动重定向。
    • 不在一个slot下的键值,是不能使用mget,mset等多键操作。
    • 可以通过{}来定义组的概念,从而使key中{}内相同内容的键值对放到一个slot中去

    查询命令

    • CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。
    • CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量
    • CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键

    9.5.5 故障恢复

    • 如果主节点下线?从节点能否自动升为主节点?
      可以
    • 主节点恢复后,主从关系会如何?
      回复后变为slave
    • 如果所有某一段插槽的主从节点都当掉,redis服务是否还能继续?
      假设
      192.168.136.128:6379 master
      192.168.136.130:6379 master
      192.168.136.129:6379 master
      192.168.136.131:6379 是 192.168.136.128:6379 的从服务器
      192.168.136.132:6379 是 192.168.136.130:6379 的从服务器
      192.168.136.133:6379 是 192.168.136.129:6379 的从服务器
      并且插槽分配如下:
      192.168.136.128:6379master插槽为0-5460
      192.168.136.130:6379master插槽为5461-10922
      192.168.136.129:6379master插槽为10923-16383
      如果128和131挂掉之后 name插槽0-5460则不可用 此时
      如果配置文件中配置项
      cluster-require-full-coverage 为yes 时
      则表示16384个slot都正常的时候才能对外提供服务 (此时主从都挂掉 整个集群down掉)
      cluster-require-full-coverage 为no 时
      则表示16384个slot如果部分slot出现问题也对外提供服务(此时主从都挂掉 整个集群不会down)

    9 Redis 集群(redis5)

    版本差异

    Redis 5版本之后 通过redis-cli客户端命令来创建集群 不用安装ruby
    Redis 5 集群命令

    ./src/redis-cli --cluster create -a 123456 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
    

    -a 参数为 集群密码
    cluster-replicas 1 代表 一个master后有几个slave,1代表为1个slave节点

  • 相关阅读:
    MFC中添加ToolTip提示框
    神经网络算法程序
    DOS命令大全(经典收藏)
    axure团队合作开发原型图
    POJ 3233 Matrix Power Series(矩阵高速功率+二分法)
    了解你的家公家IP
    HDOJ 3518 Boring counting
    模板方法模式的房间改造-组合查询
    6最好的之一 HTML5/CSS3 演示(PPT)框架
    试想一下,在代码学习Swift!
  • 原文地址:https://www.cnblogs.com/doagain/p/14968978.html
Copyright © 2011-2022 走看看