Redis分布式缓存集群技术(也支持持久化),是关系型数据库的互补产品
特点:追求高性能\高并发,对数据一致性要求比数据库要差一些.

# 1. Redis在集群架构中的角色及工作流程
    1)内存缓存功能
       1.关系数据库前端的缓存
       2.集群后端共享session
     
    2)独立做数据库:
       3.粉丝关注业务
       4.排行榜(音乐\游戏)

# 2. 数据库产品介绍

RDBMS :MySQL,PG,Oracle,MSSQL,
NoSQL : Redis,MongoDB,ES
NewSQL----->分布式数据库架构 tidb

###趋势
国产操作系统:麒麟Linux:老男孩合作伙伴,Linux运维必会
国产数据库:  TIDB/Pingcap :老男孩合作伙伴,专业DBA必会

进军国产数据库企业,企业内训\产品代理\产品项目方案\实施\项目维护

# 3.Redis是什么?
分布式缓存产品,数据存储形式是key--value
例如:oldboy--->oldboy已经35岁了.读取是读取oldboy,显示oldboy已经35岁了
oldboy--->35

# 4. key-value缓存产品介绍及对比
memcached 纯内存(大公司做二次开发,产品为memcacheDB,内存+持久化)
ttserver  内存+持久化 日本人开发的
redis     内存+持久化    胜出
Tair

Memcached:纯内存
优点:高性能读写、单一数据类型、支持客户端式分布式集群、一致性hash(memcache,squid)
      多核结构、多线程读写性能高。
缺点:无持久化、节点故障可能出现缓存穿透、分布式需要客户端实现、跨机房数据同步困难、架构扩容复杂度高

Redis:    优点:高性能读写、多数据类型支持、数据持久化、高可用架构、支持自定义虚拟内存、支持分布式分片集群、
单线程读写性能极高
缺点:多线程读写较Memcached慢
场景:新浪、京东、直播类平台、网页游戏

memcached与redis在读写性能的对比
    memcached 适合多用户访问,每个用户少量rw
    redis     适合少用户访问,每个用户大量rw
                
Tair:
    优点:高性能读写、支持三种存储引擎(ddb、rdb、ldb)、支持高可用、支持分布式分片集群、支撑了几乎所有淘宝业务的缓存。
    缺点:单机情况下,读写性能较其它两种产品较慢

# 5. Redis功能介绍

支持数据类型丰富     (笔试、面试)  *****
 支持持久化           (笔试、面试)  *****
 多种内存分配及回收策略
 支持事务            (面试)        ****
 支持高可用                       ****
 支持分布式分片集群   (面试)      *****
 Redis API                   **1.12.3请简述redis数据类型及应用场景?
 # 6.Redis使用场景
Memcached:多核的缓存服务,更加适合于多用户并发访问次数较少的应用场景
 Redis:单核缓存服务,单节点情况下,更加适合于少量用户,多次访问应用场景。Redis一般是单机多实例架构,配合redis集群出现。
 # 5.Redis安装部署:
1)下载:
 cd ~
 wget http://download.redis.io/releases/redis-3.2.12.tar.gz
 或上传到/data2)解压:
 tar xf redis-3.2.12.tar.gz
 mv redis-3.2.12 /usr/local/redis3)安装:
 #yum -y install gcc automake autoconf libtool make
 cd /usr/local/redis
 make4)配置环境变量:/usr/local/redis/src
 cat>>/etc/profile<<'EOF' 
 export PATH=/usr/local/redis/src:$PATH
 EOF
 tail -1 /etc/profile 
 source /etc/profile 
 echo $PATH 5)启动redis:
 redis-server & 
 [root@oldboy redis]# netstat -lntup|grep 6379         
 tcp        0      0 0.0.0.0:6379 0.0.0.0:* LISTEN      5052/redis-server * 
 tcp6       0      0 :::6379      :::*      LISTEN      5052/redis-server *                                      6)启动警告处理:
 echo '511' > /proc/sys/net/core/somaxconn
 echo never > /sys/kernel/mm/transparent_hugepage/enabled
 ulimit -SHn 65535##以上两条放入/etc/rc.local
 [root@db01 /usr/local/redis]# vim /etc/rc.local
 echo '511' > /proc/sys/net/core/somaxconn
 echo never > /sys/kernel/mm/transparent_hugepage/enabled
 ulimit -SHn 65535echo 'vm.overcommit_memory = 1' >> /etc/sysctl.conf
 sysctl -pecho "*    -    nofile  65535" >>/etc/security/limits.conf  #永久生效
 7)连接测试:
 [root@oldboy redis]# redis-cli 
 127.0.0.1:6379> set oldboy 35
 OK
 127.0.0.1:6379> get oldboy
 "35"
 127.0.0.1:6379> exit
 安装成功。# 6. Redis基本管理操作
## 6.1 基础配置文件
1)创建数据文件目录
 mkdir /data/6379 -p2)生成配置文件
 cat > /data/6379/redis.conf<<EOF
 daemonize yes
 port 6379
 logfile /data/6379/redis.log
 dir /data/6379
 dbfilename dump.rdb
 EOF
 cat /data/6379/redis.conf  3)配置文件说明
 ==redis.conf: 配置文件说明oldboy==========
 daemonize yes               #是否后台运行
 port 6379                   #默认端口
 logfile /var/log/redis.log  #日志文件位置
 dir /data/6379              #持久化文件存储位置
 dbfilename dump.rdb         #RDB持久化数据文件
 ====================================4)重启:
 #关闭
 redis-cli shutdown 
 #启动
 redis-server /data/6379/redis.conf 
 netstat -lnp|grep 6379测试:
 [root@oldboy redis]# redis-cli 
 127.0.0.1:6379> set name oldboy
 OK
 127.0.0.1:6379> get name
 "oldboy"
 127.0.0.1:6379> exit## 6.2 使用systemd管理redis
 1)关闭
 redis-cli shutdown2)创建用户并授权
 useradd redis -M -s /sbin/nologin
 chown -R redis:redis /data/63*3)生成启动文件
 cat >/usr/lib/systemd/system/redis6379.service<<EOF
 [Unit]
 Description=Redis persistent key-value database
 After=network.target
 After=network-online.target
 Wants=network-online.target[Service]
 ExecStart=/usr/local/redis/src/redis-server /data/6379/redis.conf --supervised systemd
 ExecStop=/usr/local/redis/src/redis-cli shutdown
 Type=notify
 User=redis
 Group=redis
 RuntimeDirectory=redis
 RuntimeDirectoryMode=0755[Install]
 WantedBy=multi-user.target
 EOF4)设置开机自启动,并启动检查
 [root@db01 redis]# systemctl enable redis6379
 [root@db01 redis]# systemctl start redis6379
 [root@db01 redis]# netstat -lntup|grep 637
 tcp        0      0 0.0.0.0:6379  0.0.0.0:* LISTEN      6832/redis-server * 
 tcp6       0      0 :::6379       :::*      LISTEN      6832/redis-server *  ## 6.3 redis安全配置
 redis默认开启了保护模式,只允许本地回环地址登录并访问数据库。 #禁止protected-mode
 protected-mode yes #保护模式,是否只允许本地访问取消:CONFIG SET protected-mode no
 (1)Bind :指定IP进行监听
 vim /data/6379/redis.conf
 bind 10.0.0.51  127.0.0.1(2)增加requirepass  {password}
 vim /data/6379/redis.conf
 requirepass 123 [root@oldboy redis]# cat /data/6379/redis.conf
 daemonize yes
 port 6379
 logfile /data/6379/redis.log
 dir /data/6379
 dbfilename dump.rdbbind 10.0.0.51  127.0.0.1
 requirepass 123重启:
 redis-cli shutdown 
 redis-server /data/6379/redis.conf 验证:
 方法一:
 [root@oldboy redis]# redis-cli -a 123
 127.0.0.1:6379> set oldboy 35
 OK
 127.0.0.1:6379> get oldboy
 "35"
 127.0.0.1:6379> exit方法二:
 [root@oldboy redis]# redis-cli
 127.0.0.1:6379> set oldgirl 28
 (error) NOAUTH Authentication required.
 127.0.0.1:6379> auth 123
 OK
 127.0.0.1:6379> set oldgirl 28
 OK
 127.0.0.1:6379> get oldgirl
 "28"
 127.0.0.1:6379> exit方法三:
 [root@oldboy redis]# redis-cli -a 123 -h 10.0.0.51 -p 6379
 10.0.0.51:6379> get oldgirl
 "28"
 10.0.0.51:6379> set key value
 OK
 10.0.0.51:6379> get key
 "value"
 10.0.0.51:6379> exit ## 6.3 在线查看和修改参数
 参数修改:
 1)配置文件。2)在线查看和修改参数
#在线查看
 CONFIG GET *
 CONFIG GET pro*[root@oldboy redis]# redis-cli -a 123
 127.0.0.1:6379> CONFIG GET *
 127.0.0.1:6379> CONFIG GET pro*
 1) "protected-mode"
 2) "yes" 在线设置密码:
 config set requirepass oldboy123登录验证:
 [root@db01 /usr/local/redis]# redis-cli -h 10.0.0.51 -p 6379 -a 123
 10.0.0.51:6379> get name
 (error) NOAUTH Authentication required.
 10.0.0.51:6379> auth oldboy123
 OK
 10.0.0.51:6379> get name
 "oldboy"
 10.0.0.51:6379> config set requirepass 123
 OK 配置文件详解:
 ## 6.4 redis持久化(内存数据保存到磁盘)
redis持久化方式:RDB、AOF
 1)RDB持久化
     在指定时间间隔内生成数据集的时间点快照(point-in-time snapshot)。
     优点:速度快,适合于用做备份,主从复制也是基于RDB持久化功能实现的。
     缺点:会有数据丢失
     
 rdb持久化核心配置参数:
 vim /data/6379/redis.conf
 dir /data/6379
 dbfilename dump.rdb
 =================
 save 900 1     
 save 300 10
 save 60 10000
 =================
 配置分别表示:
 900秒(15分钟)内有1个更改
 300秒(5分钟)内有10个更改
 60秒内有10000个更改  
 2)AOF持久化(append-only log file)
     类似mysql binlog
     记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集。 
     AOF文件中的命令全部以Redis协议格式来保存,新命令会被追加到文件的末尾。
     
     优点:可以最大程度保证数据不丢
     缺点:日志记录量级比较大AOF持久化配置参数:
 appendonly yes       #是否打开aof日志功能appendfsync always   #每1个更新,都立即同步到aof。*****
 appendfsync everysec #每秒讲同步一次数据到aof。
 appendfsync no       #写入工作交给操作系统,由操作系统判断缓冲区大小,统一写入到aof. 配置:
 vim /data/6379/redis.conf
 appendonly yes
 appendfsync always  面试:redis持久化方式有哪些?有什么区别?
 rdb:基于快照持久化,速度更快,一般用作备份,主从复制也是依赖于rdb持久化功能
 aof:以追加方式记录redis操作日志的文件。可以最大程度的保证redis数据安全,类似于mysql的binlog,可以每个更新记录,每秒记录。 # 7.Redis数据类型:
 Redis的数据类型非常丰富## 7.1 介绍
 String :      字符类型
 Hash:         字典类型
 List:         列表     
 Set:          集合 
 Sorted set:   有序集合 ## 7.2 KEY的通用操作
 SET                         #设置键值对
 GET                         #获取键值
 KEYS *      keys a  keys a*    #查看已存在所有键的名字   ****
 TYPE                        #返回键所存储值的类型     ****
 EXPIRE\PEXPIRE                 #以秒\毫秒设定生存时间    ***
 TTL\PTTL                     #以秒\毫秒为单位返回生存时间 ***
 PERSIST                     #取消生存时间设置            ***
 DEL                            #删除一个key
 EXISTS                         #检查是否存在
 RENAME                         #变更KEY名 例子:
 127.0.0.1:6379> set name oldboy
 OK
 127.0.0.1:6379> get name
 "oldboy"
 127.0.0.1:6379> expire name 30
 (integer) 1
 127.0.0.1:6379> ttl name
 (integer) 23
 127.0.0.1:6379> ttl name
 (integer) 21
 127.0.0.1:6379> set key 01 ex 10
 OK
 127.0.0.1:6379> ttl key
 (integer) 6
 127.0.0.1:6379> get name
 (nil)
 127.0.0.1:6379> get key
 (nil)127.0.0.1:6379> set key 01 ex 60
 OK
 127.0.0.1:6379> ttl key
 (integer) 58
 127.0.0.1:6379> get key
 "01"
 127.0.0.1:6379> persist key
 (integer) 1
 127.0.0.1:6379> ttl key
 (integer) -1
 127.0.0.1:6379> exists key
 (integer) 1
 127.0.0.1:6379> rename key oldboy
 OK
 127.0.0.1:6379> get oldboy
 "01"
 127.0.0.1:6379> del oldboy
 (integer) 1 7.3 Redis数据类型常用操作命令
1.字符串类型(string)
 基本命令
 A、 set
 B、 get
 C、 incr
 D、 decr
 E、 append常用命令
 A、 strlen
 B、 getrange
 C、 setrange
 D、 mset
 E、 mget2.哈希类型 hash
 基本命令
 A、 hset
 B、 hget
 C、 hmset
 D、 hmget
 E、 hgetall
 F、 hdel
 常用命令
 A、 hkeys
 B、 hvals
 C、 hexists3.列表 list
 基本命令
 A、 lpush
 B、 rpush
 C、 lrange
 D、 lindex
 E、 llen
 常用命令
 A、 lrem
 B、 lset
 C、 linsert4.集合类型 set
 基本命令
 A、 sadd
 B、 smembers
 C、 sismember
 D、 scard
 E、 srem
 常用命令
 A、 srandmember
 B、 spop5.有序集合类型 zset (sorted set)
 基本命令
 A、 zadd
 B、 zrange
 C、 zrevrange
 D、 zrem
 常用命令
 A、 zrangebyscore
 B、 zrevrangebyscore
 C、 zcount
 原文链接:## 7.3 Strings字符类型
1)应用场景
     a.集群session共享
     b.计数:微博数,粉丝数,订阅数、礼物数2)数据存在形式
 key:value
 (1) set name oldboy 
  
 (2)数据库学生表的2行记录:
 id   name    age  gender
 101  oldboy  20   m
 102  oldgirl 18   f
 ===============================
 MSET id 101 name oldboy  age 20 gender m  ##数据库的一行记录。
 MSET id 102 name oldgirl age 18 gender f  ##数据库的一行记录。等价于以下操作:
  set id 101 
  set name oldboy 
  set age 20 
  set gender m实践:
 10.0.0.51:6379> MSET id 101 name oldboy  age 20 gender m 
 OK
 10.0.0.51:6379> 
 10.0.0.51:6379> get id
 "101"
 10.0.0.51:6379> get name
 "oldboy"
 10.0.0.51:6379> get age
 "20"
 10.0.0.51:6379> get gender
 "m"
   
 (3)一起读出来
  Mget id name age gender
 1) "101"
 2) "oldboy"
 3) "20"
 4) "m"(4)计数器(粉丝关注)
 每点一次关注,都执行以下命令一次
 127.0.0.1:6379> incr num
 (integer) 1
 127.0.0.1:6379> incr num
 (integer) 2
 127.0.0.1:6379> incr num
 (integer) 3显示粉丝数量:
 127.0.0.1:6379> get num
 "3"暗箱操作:
 增粉:
 127.0.0.1:6379> INCRBY num 1000
 (integer) 1003
 127.0.0.1:6379> get num
 "1003"减粉:
 127.0.0.1:6379> DECRBY num 1000
 (integer) 3
 127.0.0.1:6379> get num
 "3" ## 7.4 hash类型(字典类型)
1)应用场景:
 存储部分变更的数据,如用户信息等。最接近[mysql表结构的一种类型]
 主要是做数据库缓存的存储类型。存数据:
 hmset stu1 id 101 name oldboy age 20 gender m
 hmset stu2 id 102 name oldgirl age 21 gender f取数据:
 HMGET stu1 id name age gender
 HMGET stu2 id name age gender案例:模拟redis缓存应用:
1.初次访问缓存,没有数据,然后请求读MySQL:
 db01 [world]>select * from world.city limit 10;
 +----+----------------+-------------+---------------+------------+
 | ID | Name           | CountryCode | District      | Population |
 +----+----------------+-------------+---------------+------------+
 |  1 | Kabul          | AFG         | Kabol         |    1780000 |
 |  2 | Qandahar       | AFG         | Qandahar      |     237500 |
 |  3 | Herat          | AFG         | Herat         |     186800 |
 |  4 | Mazar-e-Sharif | AFG         | Balkh         |     127800 |
 |  5 | Amsterdam      | NLD         | Noord-Holland |     731200 |
 |  6 | Rotterdam      | NLD         | Zuid-Holland  |     593321 |
 |  7 | Haag           | NLD         | Zuid-Holland  |     440900 |
 |  8 | Utrecht        | NLD         | Utrecht       |     234323 |
 |  9 | Eindhoven      | NLD         | Noord-Brabant |     201843 |
 | 10 | Tilburg        | NLD         | Noord-Brabant |     193238 |
 +----+----------------+-------------+---------------+------------+
 2.通过把取出的语句拼接成redis命令
 实际工作(通过程序处理)
 select concat("hmset city_",id," id ",id," name ",name) from world.city limit 10 into outfile '/tmp/hmset.txt'3.拼接成redis操作命令
 [root@db01 ~]# cat /tmp/hmset.txt 
 hmset city_1 id 1 name Kabul
 hmset city_2 id 2 name Qandahar
 hmset city_3 id 3 name Herat
 hmset city_4 id 4 name Mazar-e-Sharif
 hmset city_5 id 5 name Amsterdam
 hmset city_6 id 6 name Rotterdam
 hmset city_7 id 7 name Haag
 hmset city_8 id 8 name Utrecht
 hmset city_9 id 9 name Eindhoven
 hmset city_10 id 10 name Tilburg3.把数据库数据缓存到Redis:
 cat /tmp/hmset.txt| redis-cli -a 123 -h 10.0.0.51 -p 63794.读取Redis缓存返回用户
 [root@db01 redis]# redis-cli -a 123 -h 10.0.0.51 -p 6379
 10.0.0.51:6379> hmget city_1 id name
 1) "1"
 2) "Kabul"
 10.0.0.51:6379> hmget city_2 id name
 1) "2"
 2) "Qandahar

## 7.5 LIST(列表)
1)应用场景
消息队列系统,比如sina微博\微信朋友圈

在Redis中的最新微博ID使用了常驻缓存,这是一直更新的。
但是做了限制不能超过5000个ID,因此获取ID的函数会一直询问Redis。
只有在start/count参数超出了这个范围的时候,才需要去访问数据库。
系统不会像传统方式那样“刷新”缓存,Redis实例中的信息永远是一致的。

SQL数据库(或是硬盘上的其他类型数据库)只是在用户需要获取“很远”的数据时才会被触发,
 而主页或第一个评论页是不会麻烦到硬盘上的数据库了。 微信发朋友圈例子:
 127.0.0.1:6379> LPUSH wechat "today is nice day !"
 127.0.0.1:6379> LPUSH wechat "today is bad day !"
 127.0.0.1:6379> LPUSH wechat "today is good day !"
 127.0.0.1:6379> LPUSH wechat "today is rainy day !"
 127.0.0.1:6379> LPUSH wechat "today is friday!" 倒序输出:最新的再上面
 127.0.0.1:6379> lrange wechat 0 5
 1) "today is friday!"
 2) "today is rainy day !"
 3) "today is good day !"
 4) "today is bad day !"
 5) "today is nice day ! ## 7.6 SET集合类型(MySQL join/union)
1)应用场景:
 案例:在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。
 Redis还为集合提供了求交集、并集、差集等操作,可以非常方便的实现如共同关注、共同喜好、二度好友等功能,
 对上面的所有集合操作,你还可以使用不同的命令选择将结果返回给客户端还是存集到一个新的集合中。例子:
 2)a,b两人
 127.0.0.1:6379> sadd a 1 2 3 4 5 6
 (integer) 6127.0.0.1:6379> sadd b 5 6 7 8 9 0
 (integer) 6
 ....3)结婚了摆酒请客
 127.0.0.1:6379> SUNION a b
  1) "0"
  2) "1"
  3) "2"
  4) "3"
  5) "4"
  6) "5"
  7) "6"
  8) "7"
  9) "8"
 10) "9"
 ......4)吵架了,找来共同好友说和
 127.0.0.1:6379> SINTER a b
 1) "5"
 2) "6"
 ........ #左边不同的取出
 127.0.0.1:6379> SDIFF a b 
 1) "1"
 2) "2"
 3) "3"
 4) "4"
 127.0.0.1:6379> SDIFF b a
 1) "0"
 2) "7"
 3) "8"
 4) "9"
 .....## 6.7 SortedSet(有序集合)
1)应用场景:排行榜,取TOP N操作
这个需求与上面需求的不同之处在于,前面操作以时间为权重,这个是以某个条件为权重,比如按顶的次数排序,
 这时候就需要我们的sorted set出马了,将你要排序的值设置成sorted set的score,将具体的数据设置成相应的value,每次只需要执行一条ZADD命令即可。 10.0.0.51:6379> zadd top 0 smlt 0 fskl 0 fshkl 0 lzlsfs 0 wdhbx 0 wxg 
 (integer) 610.0.0.51:6379> zrevrange top 0 2
 1) "wxg"
 2) "wdhbx"
 3) "smlt"
 10.0.0.51:6379> ZINCRBY top 1000 smlt
 "1000"
 10.0.0.51:6379> ZINCRBY top 5000 fskl
 "5000"
 10.0.0.51:6379> ZINCRBY top 8000 fshkl
 "8000"
 10.0.0.51:6379> ZINCRBY top 9000 lzlsfs
 "9000"
 10.0.0.51:6379> ZINCRBY top 6000 wdhbx
 "6000"
 10.0.0.51:6379> ZINCRBY top 3000 wxg
 "3000"排名前三:
 10.0.0.51:6379> zrevrange top 0 2
 1) "lzlsfs"
 2) "fshkl"
 3) "wdhbx" 排名前三:
 127.0.0.1:6379> ZREVRANGE top 0 2 
 1) "wxg"
 2) "fshkl"
 3) "smlt"排名前三:显示票数
 10.0.0.51:6379> zrevrange top 0 3 withscores
 1) "lzlsfs"
 2) "9000"
 3) "fshkl"
 4) "8000"
 5) "wxg"
 6) "6000"
 7) "wdhbx"
 8) "6000"

# 8.Redis事务

1)redis事务介绍与mysql事务区别
redis支持简单的事务;
基于队列实现的。
mysql事务是基于事务日志和锁机制实现的。
redis是乐观锁机制。

2)开启事务功能(multi)
见图:

一个事务:
 multi 
 command1      
 command2
 exec 事务回滚:
 multi 
 command1      
 command2
 discard

3条语句作为一个组,并没有真正执行,而是被放入同一队列中。
如果是执行discard,会直接丢弃队列中所有的命令,而不是做回滚。

exec
当执行exec时,对列中所有操作,要么全成功要么全失败

例子:
 127.0.0.1:6379> multi
 OK
 127.0.0.1:6379> set name1 oldboy
 QUEUED
 127.0.0.1:6379> set name2 oldgirl
 QUEUED
 127.0.0.1:6379> exec
 1) OK
 2) OK
 127.0.0.1:6379> get name1
 "oldboy"
 127.0.0.1:6379> mget name1 name2
 1) "oldboy"
 2) "oldgirl"
 127.0.0.1:6379> multi
 OK
 127.0.0.1:6379> set name3 zhangsan
 QUEUED
 127.0.0.1:6379> set name4 lisi
 QUEUED
 127.0.0.1:6379> discard
 OK
 127.0.0.1:6379> mget name3 name4
 1) (nil)
 2) (nil)#  9.redis(Master-Replicas) *****
redis主从



## 9.1 主从作用:
1. 数据冗余:主从复制实现数据热备份,是持久化之外的数据冗余方式。

2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速故障恢复。

3. 负载均衡:在主从复制基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务
(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是
在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。

4. 读写分离:可以用于实现读写分离,主库写、从库读,读写分离不仅可以提高服务器的负载能力,
同时可根据需求的变化,改变从库的数量;

5. 高可用:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用基础。

## 9.2 主从原理:
1)全量同步
Redis全量复制一般发生在Slave初始化阶段,这时Slave需要将Master上的所有数据都复制一份。具体步骤如下:
-  从服务器通过slaveof 10.0.0.51 6379命令连接主服务器,并发送SYNC命令给主库;
-  主服务器接收到SYNC命名后,开始执行BGSAVE命令,生成RDB文件并使用缓冲区记录此后执行的所有写命令;
-  主服务器BGSAVE执行完后,向所有从服务器发送快照文件,并在发送期间继续记录被执行的写命令;
-  从服务器收到快照文件后丢弃所有旧数据,载入收到的快照;
-  主服务器快照发送完毕后,开始向从服务器发送缓冲区中的写命令;
-  从服务器完成对快照的载入,开始接收命令请求,并执行来自主服务器缓冲区的写命令;
-  所有复制相关信息,从info信息中都可以查到.即使重启任何节点,他的主从关系依然都在.
-  如果发生主从关系断开时,从库数据没有任何损坏,在下次重连之后,从库发送PSYNC给主库
-  主库只会将从库缺失部分的数据同步给从库应用,达到快速恢复主从的目的

2)增量同步
Redis增量复制是指Slave初始化后开始正常工作时主服务器发生的写操作同步到从服务器的过程。
增量复制的过程主要是主服务器每执行一个写命令就会向从服务器发送相同的写命令,从服务器接收并执行收到的写命令。

3)Redis主从同步策略
主从刚刚连接的时候,进行全量同步;全同步结束后,进行增量同步。当然,如果有需要,slave在任何时候都可以发起全量同步。redis 策略是,无论如何,首先会尝试进行增量同步,如不成功,要求进行全量同步。

## 9.2 主从数据一致性保证,类似MySQL半同步
Redis的min-slaves-to-write和min-slaves-max-lag两个选项可以防止主服务器在不安全的情况下执行写命令
举个例子,如果我们向主服务器提供以下设置:
min-slaves-to-write 3  #(最小从服务器数)
min-slaves-max-lag  10  #(从服务器最大确认延迟)

那么在从服务器的数量少于3个,或者三个从服务器的延迟(lag)值都大于或等于10秒时,主服务器拒绝执行写命令,
这里的延迟值就是上面提到的INFO replication命令的lag值

[root@db01 ~]# redis-cli -p 6381 -a 123 config get min-slaves*
 1) "min-slaves-to-write"
 2) "0"
 3) "min-slaves-max-lag"
 4) "10"

## 9.3 主库是否要开启持久化?
1)为了缓解主redis服务器写磁盘压力带来的开销,可以配置让主redis不在将数据持久化到磁盘,
而是通过连接让一个配置的从redis服务器及时的将相关数据持久化到磁盘,不过这样会存在一个问题,
就是主redis服务器一旦重启,因为主redis服务器数据为空,这时候通过主从同步可能导致从redis
服务器上的数据也被清空;
2)主库要开持久化,主redis服务器写磁盘压力带来的开销,重启数据不会丢失。

# 10. 主从复制实践

1、环境:
准备两个或两个以上redis实例

mkdir /data/638{0..2} -p
配置文件示例:
 cat >> /data/6380/redis.conf <<EOF
 port 6380
 daemonize yes
 pidfile /data/6380/redis.pid
 loglevel notice
 logfile "/data/6380/redis.log"
 dbfilename dump.rdb
 dir /data/6380
 requirepass 123
 masterauth 123
 EOF cat >>   /data/6381/redis.conf <<EOF
 port 6381
 daemonize yes
 pidfile /data/6381/redis.pid
 loglevel notice
 logfile "/data/6381/redis.log"
 dbfilename dump.rdb
 dir /data/6381
 requirepass 123
 masterauth 123
 EOF cat >>   /data/6382/redis.conf <<EOF
 port 6382
 daemonize yes
 pidfile /data/6382/redis.pid
 loglevel notice
 logfile "/data/6382/redis.log"
 dbfilename dump.rdb
 dir /data/6382
 requirepass 123
 masterauth 123
 EOF 启动:
 redis-server /data/6380/redis.conf
 redis-server /data/6381/redis.conf
 redis-server /data/6382/redis.conf角色说明:
     主节点:6380
     从节点:6381、6382 2、开启主从:
 6381/6382命令行:redis-cli -p 6381 -a 123 SLAVEOF 127.0.0.1 6380
 redis-cli -p 6382 -a 123 SLAVEOF 127.0.0.1 6380 3、查询主从状态
 redis-cli -p 6380 -a 123 info replication
 redis-cli -p 6381 -a 123 info replication
 redis-cli -p 6382 -a 123 info replication测试
 [root@oldboy redis]# redis-cli -p 6380 -a 123 set oldboy 28
 OK
 [root@oldboy redis]# redis-cli -p 6381 -a 123 get oldboy
 "28"
 [root@oldboy redis]# redis-cli -p 6382 -a 123 get oldboy
 "28"
 [root@oldboy redis]# redis-cli -p 6380 -a 123 del oldboy
 (integer) 1
 [root@oldboy redis]# redis-cli -p 6381 -a 123 get oldboy
 (nil)
 [root@oldboy redis]# redis-cli -p 6382 -a 123 get oldboy
 (nil)4. 解除主从身份
 redis-cli -p 6382 -a 123 SLAVEOF no one
 验证:
 [root@oldboy redis]# redis-cli -p 6380 -a 123 set oldgirl 21
 OK
 [root@oldboy redis]# redis-cli -p 6381 -a 123 get oldgirl
 "21"
 [root@oldboy redis]# redis-cli -p 6382 -a 123 get oldgirl
 (nil)  ##身份解除所以,没数据。5.从库只读
 slave-read-only #参数控制的
 [root@db01 redis]# redis-cli -p 6382 -a 123 config get *read*
 1) "slave-read-only"
 2) "yes"默认只读:
 [root@db01 ~]# redis-cli -p 6381 -a 123 set k y
 (error) READONLY You can't write against a read only slave.