主从复制同步
day12 部署集群环境
IP 规划
• redis 服务器 ip 地址及端口规划
– redisA 192.168.4.51 6351
– redisB 192.168.4.52 6352
– redisC 192.168.4.53 6353
– redisD 192.168.4.54 6354
– redisE 192.168.4.55 6355
– redisF 192.168.4.56 6355
拓展图
集群工作原理
创建 Redis 集群
装包
• 在 6 台主机上做如下配置,并运行 redis 服务
#yum -y install gcc gcc-c++
#tar -zxvf redis-4.0.8.tar.gz
#cd redis-4.0.8/
#make
#make install
#./utils/install_server.sh
• 修改配置文件
#vim /etc/redis/redis.conf
bind IP 地址 // 只写物理接口 IP 地址
daemonize yes // 守护进程方式运行
port xxxx // 端口号不要使用默认的 6379
cluster-enabled yes // 开启集群
cluster-config-file nodes.conf // 集群的配置文件不要使用默认的名称
cluster-node-timeout 5000 // 请求超时 5 秒
装包:
1)在执行创建集群命令的主机安装ruby软件包(192.168.4.51)
安装解释ruby代码的软件包
[root@host51 ~]#cd sofd/redis
[root@host51 ~]# yum -y install ruby rubygems
[root@host51 ~]# rpm -q rubygems ruby
rubygems-2.0.14.1-30.el7.noarch
ruby-2.0.0.648-30.el7.x86_64
[root@host51redis-cluster]#rpm -ivh --nodeps ruby-devel-2.0.0.648-30.el7.x86_64.rpm
如果失败
1.先停服务
/etc/init.d/redis_6379 stop
2.删掉配置 rm -rf
/var/lib/redis/6379/nodes-6351.conf
3.起服务
/etc/init.d/redis_6379 stop
安装ruby连接redis 接口程序 gem
[root@host51 redis-cluster]# which gem
/usr/bin/gem
[root@host51 redis-cluster]# gem install redis-3.2.1.gem
Successfully installed redis-3.2.1
.....
[root@host51 redis]# redis-trib.rb create --replicas 1 \
192.168.4.51:6351 \
192.168.4.52:6352 \
192.168.4.53:6353 \
192.168.4.54:6354 \
192.168.4.55:6355 \
192.168.4.56:6356 \
[OK] All 16384 slots covered.
2)每台 redis服务 在本机登录 查看集群信息
[root@host51 ~]# redis-cli -c -h 192.168.4.51 -p 6051
3) -c 连接集群中的主机
[root@host51 ~]# redis-cli -c -h 192.168.4.51 -p 6051 //加c连集群
192.168.4.51:6051> CLUSTER info # 查看集群信息
192.168.4.51:6051> CLUSTER nodes # 查看本机信息
192.168.4.51:6051> quit
4)测试集群
• 在其中任意一台上存储数据 ,在其他任意一台上都可以获取数据。
存数据 set name jerry
取数据 get name
5)查看谁是谁的从
[root@host51 ~]# cat /var/lib/redis/6379/nodes-6351.conf
>f31ac9e191df6f687e869920d4ef41d91d35b2f2 192.168.4.52:6352@16352 master - 0 1528426466000 2 connected 5461-10922
>3946ea34eda4c157d20a31d4ba8c5d00dd0f8293 192.168.4.55:6355@16355slave8a09a4308efbe3d7446b16894c35b7b283feffdc 0 1528426466817 5 connected
>1f496b03d550b7c6762f661893b011bf05cec65f 192.168.4.53:6353@16353 master - 0 1528426467821 3 connected 10923-16383
>797394b58fb1172f853d25477c2781f87d2fc57f 192.168.4.56:6356@16356 slave f31ac9e191df6f687e869920d4ef41d91d35b2f2 0 1528426466000 6 connected
>8a09a4308efbe3d7446b16894c35b7b283feffdc 192.168.4.51:6351@16351 myself,master - 0 1528426467000 1 connected 0-5460
>462a971184ceb3fd1def7a7b72069225a95cf14c 192.168.4.54:6354@16354 slave 1f496b03d550b7c6762f661893b011bf05cec65f 0 1528426468000 4 connected
vars currentEpoch 6 lastVoteEpoch 0
- 从上得出:
主 从
51 55
52 56
53 54
- 储存规律
192.168.4.52:6352> set n 40
-> Redirected to slot [3432] located at 192.168.4.51:6351
OK
192.168.4.51:6351> keys *
1) "n"
192.168.4.51:6351> get n
"40"
注意:
n crc16 3 % 16383 0-5460
(决定存在51)自动调51
管理命令
redis-cli 命令
• 查看命令帮助
– redis-cli -h
• 常用选项
– -h IP 地址
– -p 端口
– -c 访问集群redis-trib.rb 脚本
• 语法格式
– Redis-trib.rb
选项 参数
• 选项
– add-node 添加新节点
– check 对节点主机做检查
– reshard 对节点主机重新分片
– add-node --slave 添加从节点主机
– del-node 删除节点主机
例子:
1)添加集群主库
[root@host51src]#./redis-trib.rb add-node 192.168.4.50:6350 192.168.4.51:6351
2)删除集群主库
[root@host51 src]# redis-trib.rb del-node 192.168.4.51:6351 3bbad4f4aa9fee1f78a9f266458b163095c786ae
3)添加集群从库
添加slave角色主机
1 主机运行redis服务 并设置集群配置
2 添加slave角色主机
]# redis-trib.rb add-node --slave 要添加到集群中主机ip:端口 集群中已有的任意一个主机的ip:端口
[root@host51 src]#./redis-trib.rb add-node --slave 192.168.4.57:6357 192.168.4.51:6351
4)重新分片
删除节点主机
1 删除master角色的节点主机
1.1 移除占用的hash槽(slot)
1.2 删除主机
还原主从集群:
rm -rf /var/lib/redis/6379/*
/etc/init.d/redis_6379 stop
/etc/init.d/redis_6379 start
]#redis-trib.rb reshard 192.168.4.51:6051
4096 移除hash槽的个数
主机id 目标主机id
主机id 源主机id
done 设置完毕
yes 提交
[root@host51 src]# ./redis-trib.rb reshard 192.168.4.51:6351
How many slots do you want to move (from 1 to 16384)? 4096
What is the receiving node ID? 新的主机,分配4096个糟
Source node #1: 从多的主机节点分配,这里填要分配的ip,yes分配
5)察看分配结果 ,检查集群主机状态信息
[root@host51 src]# redis-trib.rb check 192.168.4.51:6351
主从复制概述 day13
- 拓扑结构
• 主服务器数据自动同步到从服务器
- 主从复制工作原理
• 工作原理
– Slave 向 maste 发送 sync 命令
– Master 启动后台存盘进程,同时收集所有修改数据命令
– Master 执行完后台存盘进程后,传送整个数据文件到slave 。
– Slave 接收数据文件后,将其存盘并加载到内存中完成首次完全同步
– 后续有新数据产生时, master 继续将新的所以收集到的修改命令依次传给 slave ,完成同步。主从复制缺点
• 缺点
– 网络繁忙,会产生数据同步延时问题
– 系统繁忙,会产生数据同步延时问题
- 配置从库
• 配置从库 192.168.4.52/24
– redis 服务运行后,默认都是 master 服务器
– 修改服务使用的 IP 地址 bind 192.168.4.X
[root@redis52 ~]# redis-cli -h 192.168.4.52 -p 6352
192.168.4.52:6379> info replication // 查看主从配置信息
192.168.4.52:6379> SLAVEOF 192.168.4.51 6351
OK
192.168.4.52:6379> info replication 命令行指定主库
# Replication SLAVEOF 主库 IP 地址 端口号
role:slave
master_host:192.168.4.51
master_port:6379反客为主
重起服务变成主库:
/etc/init.d/redis_6379 stop
/etc/init.d/redis_6379 start
- 反客为主
• 反客为主
– 主库宕机后,手动将从库设置为主库
[root@redis52 ~]# redis-cli -h 192.168.4.52
192.168.4.52:6379> SLAVEOF no one // 设置为主库
OK
192.168.4.52:6379> info replication
# Replication
role:master
- 哨兵模式
• 哨兵模式
– 主库宕机后,从库自动升级为主库
– 在 slave 主机编辑 sentinel.conf 文件
– 在 slave 主机运行哨兵程序
[root@redis52 ~]# vim /etc/sentinel.conf
sentinel monitor redis51 192.168.4.51 6379 1
:wq
[root@redis52 ~]# redis-sentinel /etc/sentinel.conf
- 配置带验证的主从复制
• 配置 master 主机
– 设置连接密码 ,启动服务,连接服务
[root@redis51 ~]# sed -n '70p;501p' /etc/redis/6379.conf
bind 192.168.4.51
requirepass 123456 // 密码
[root@redis51 ~]# /etc/init.d/redis_6379 start
Starting Redis server...
[root@redis51 ~]# redis-cli -h 192.168.1.111 -a 123456 -p 6379
192.168.4.51:6379>
• 配置文件,脚本停服务
[root@host51 ~]# redis-cli -h 192.168.4.51 -a 123456 -p 6351 shutdown
[root@host51 ~]# vim /etc/init.d/redis_6379
... ...
$CLIEXEC -h 192.168.4.51 -p 6351 -a 123456 shutdown
[root@redis51 ~]# /etc/init.d/redis_6379 start
配置带验证的主从复制 ( 续 1 )
• 配置 slave 主机
– 指定主库 IP ,设置连接密码,启动服务
[root@redis52 ~]# sed -n '70p;282p;289p' /etc/redis/6379.conf
bind 192.168.4.52
slaveof 192.168.4.51 6379 // 主库 IP 与端口
masterauth 123456 // 主库密码
[root@redis52 ~]#
[root@redis52 ~]# /etc/init.d/redis_6379 start
Starting Redis server...
[root@redis52 ~]# redis-cli -h 192.168.4.52
192.168.4.52:6379> INFO replication
# Replication
role:slave
master_host:192.168.4.51
master_port:6379
持久化之 RDB
- RDB 介绍
• 全称 Reids DataBase
– 数据持久化方式之一
– 在指定时间间隔内,将内存中的数据集快照写入硬盘。
– 术语叫 Snapshot 快照。
– 恢复时,将快照文件直接读到内存里。
- 相关配置参数 ( /var/lib/redis/6379/dump.rdb)
• 文件名
– dbfilename “dump.rdb” // 文件名
– save “” // 禁用 RDB
• 数据从内存保存到硬盘的频率
– save 900 1 // 900 秒内且有 1 次修改存盘
– save 300 10 //300 秒内且有 10 次修改存盘
– save 60 10000 //60 秒内且有 10000 修改存盘
• 手动立刻存盘
– > save // 阻塞写存盘
– > bgsave // 不阻塞写存盘
- 相关配置参数 ( 续 1)
• 压缩
– rdbcompression yes | no
• 在存储快照后,使用 crc16 算法做数据校验
– rdbchecksum yes|no
• bgsave 出错停止写操作 , 对数据一致性要求不高设置为 no
– stop-writes-on-bgsave-error yes|no
- 使用 RDB 文件恢复数据
• 备份数据
– 备份 dump.rdb 文件到其他位置
– ~]# cp 数据库目录 /dump.rdb
- 备份目录
• 恢复数据
– 把备份的 dump.rdb 文件拷贝回数据库目录 , 重启 redis 服务
– cp 备份目录 /dump.rdb 数据库目录 /
– /etc/redid/redis_ 端口 start
例子:
[root@host53 ~]# redis-cli -h 192.168.4.53 -p 6353
192.168.4.53:6353> set v1 11
192.168.4.53:6353> save
[root@host53 6379]# cp dump.rdb dump.rdb.back
192.168.4.53:6353> flushall
[root@host53 6379]# /etc/init.d/redis_6379 stop
[root@host53 6379]# cp dump.rdb.back dump.rdb
[root@host53 6379]# /etc/init.d/redis_6379 start
- RDB 优点 / 缺点
• RDB 优点
– 持久化时, Redis 服务会创建一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件;整个过程中主进程不做任何 IO 操作,这就确保了极高的性能。
– 如果要进程大规模数据恢复,且对数据完整行要求不是非常高,使用 RDB 比 AOF 更高效。
• RDB 的缺点
– 意外宕机,最后一次持久化的数据会丢失。
持久化之 AOF
- AOF 介绍
• 只追加操作的文件
– Append Only File
– 记录 redis 服务所有写操作。
– 不断的将新的写操作,追加到文件的末尾。
– 使用 cat 命令可以查看文件内容
• 相关配置参数
[root@host53 6379]# sed -n '673p' /etc/redis/6379.conf
• 文件名
– appendfilename "appendonly.aof" // 文件名
– appendonly yes // 启用 aof ,默认 no
• AOF 文件记录,写操作的三种方式
– appendfsync always // 有新的写操作立即记录,性能差,完整性好。
– appendfsync everysec // 每秒记录一次,宕机时会丢失 1 秒的数据
– appendfsync no // 从不记录
- 相关配置参数 ( 续 1)
• 日志重写 ( 日志文件会不断增大 ) ,何时会触发日志重写?
– redis 会记录上次重写时 AOF 文件的大小,默认配置
是当 aof 文件是上次 rewrite 后大小的 1 倍且文件大于
64M 时触发。
– auto-aof-rewrite-percentage 100
– auto-aof-rewrite-min-size 64mb
- 相关配置参数 ( 续 2)
• 修复 AOF 文件,
– 把文件恢复到最后一次的正确操作
[root@redis53 6379]# redis-check-aof --fix appendonly.aof
0x83: Expected \r\n, got: 6166
AOF analyzed: size=160, ok_up_to=123, diff=37
This will shrink the AOF from 160 bytes, with 37 bytes, to 123
bytes
Continue? [y/N]: y
Successfully truncated AOF
• 备份数据
– 备份 dump.rdb 文件到其他位置
– ~]# cp 数据库目录 /appendonly.aof
备份目录
• 恢复数据
– 把备份的 dump.rdb 文件拷贝回数据库目录 , 重启 redis 服务
– cp 备份目录/appendonly.aof 数据库目录 /
– /etc/redid/redis_ 端口 start
- AOF 优点 / 缺点
• RDB 优点
– 可以灵活的设置同步持久化 appendfsync alwayls 或
异步持久化 appendfsync verysec
– 宕机时,仅可能丢失 1 秒的数据
• RDB 的缺点
– AOF 文件的体积通常会大于 RDB 文件的体积。执行 fs
ync 策略时的速度可能会比 RDB 慢。
************************************************************************
例子:
[root@host53 ~]# redis-cli -h 192.168.4.53 -p 6353
192.168.4.53:6353> set v1 11
192.168.4.53:6353> save
[root@host53 6379]# cp dump.rdb dump.rdb.back
192.168.4.53:6353> flushall
1.删掉一些数据进行修复
[root@redis53 6379]# vim appendonly.aof
[root@redis53 6379]# redis-check-aof --fix appendonly.aof
[root@host53 6379]# /etc/init.d/redis_6379 stop
[root@host53 6379]# /etc/init.d/redis_6379 start
2.完整恢复
[root@host53 6379]# /etc/init.d/redis_6379 stop
[root@host53 6379]# cp dump.rdb.back dump.rdb
[root@host53 6379]# /etc/init.d/redis_6379 start
**********************************************************************
String 字符串
- 字符串操作
• set key value [ex seconds] [px milliseconds] [nx|xx]
– 设置 key 及值,过期时间可以设置为秒或毫秒为单位
– nx 只有 key 不存在,才对 key 进行操作
– xx 只有 key 已存在,才对 key 进行操作
• setrange key offset value
– 从偏移量开始复写 key 的特定位的值
>set first "hello world"
>setrange first 6 “Redis” // 改写为 hello Redis
• strlen key
– 统计字串长度
>strlen first
- 字符串操作(续 1 )
• append key value
– 字符存在则追加,不存在则创建 key 及 value
– 返回值为 key 的长度
>append myname jacob
• setbit key offset value
– 对 key 所存储字串,设置或清除特定偏移量上的位 (bit)
– Value 值可以为 1 或 0 , offset 为 0~2^32 之间
– key 不存在,则创建新 key
>setbit bit 0 1 //尾数1,计数1
>setbit bit 1 0 //尾数0,不记数
>bitcount bit // 结果为 2
bit: 第 0 位为 1 ,第一位为 0
- 字符串操作(续 2 )
• bitcount key
– 统计字串中被设置为 1 的比特位数量
>setbit bits 0 1 //0001
>setbit bits 3 1 //1001
>bitcount bits // 结果为 2
记录网站用户上线频率,如用户 A 上线了多少天等类似的数据如用户在某天上线,则使用 setbit ,以用户名为 key ,将网站上线日为 offset ,并在该 offset 上设置 1 ,最后计算用户总上线次数时,使用 bitcount 用户名即可这样,即使网站运行 10 年,每个用户仅占用 10*365 比特位即 456字节即可
>setbit peter 100 1 // 网站上线 100 天用户登录了一次
>setbit peter 105 1 // 网站上线 105 天用户登录了一次
>bitcount peter //网站上线peter 用户总登录了2次
- 字符串操作(续 3 )
• decr key
– 将 key 中的值减 1 , key 不存在则先初始化为 0 ,再减 1
>set test 10
>decr test
• decrby key decrement
– 将 key 中的值,减去 decrement
>set count 100
>decrby count 20
• get key
– 返回 key 所存储的字符串值
– 如果 key 不存在则返回特殊值 nil
– 如果 key 的值不是字串,则返回错误, get 只能处理字串
例子:
>set test 10
>decr test (10-1=9)
(integer) 9
> decrby test 3
(integer) 6
字符串操作(续 4 )
• getrange key start end
– 返回字串值中的子字串,截取范围为 start 和 end
– 负数偏移量表述从末尾计数, -1 表示最后一个字符, -2表示倒数第二个字符
>set first "hello,the world"
>getrange first -5 -1
"world" //最后的1到五位
>getrange first 0 4
"hello" //0.1.2.3.4位
>getrange first 10 15
"world" //第10位到15位
- 字符串操作(续 5 )
• incr key
– 将 key 的值加 1 ,如果 key 不存在,则初始为 0 后再加 1
– 主要应用为计数器
>set page 20
>incr page //后面不附值,默认执行一次加1,结果为21
• incrby key increment
– 将 key 的值增加 increment
>incrby page 2 //执行一次值加2
- 字符串操作(续 6 )
• incrbyfloat key increment
– 为 key 中所储存的值加上浮点数增量 increment
>set num 16.1
>incrbyfloat num 1.1
"17.2"
• mget key [key...]
– 一次获取一个或多个 key 的值,空格分隔, < 具有原子性>
• mset key value [key value ...]
– 一次设置多个 key 及值,空格分隔, < 具有原子性 >
例子:
set iphone "1234564345"
setrange iphone 3 ****
get iphone
Hash 表
- Hash 表简介
• Redis hash 是一个 string 类型的 field 和 value 的映射表
• 一个 key 可对应多个 field ,一个 field 对应一个 value
• 将一个对象存储为 hash 类型,较于每个字段都存储成string 类型更能节省内存
- Hash 表操作
• hset key field value
– 将 hash 表中 field 值设置为 value
>hset site google 'www.g.cn’
>hset site baidu 'www.baidu.com'
• hget key filed
– 获取 hash 表中 field 的值
>hget site google
- Hash 表操作(续 1 )
• hmset key field value [field value...]
– 同时给 hash 表中的多个 field 赋值
>hmset site google www.g.cn baidu www.baidu.com
• hmget key field [field...]
– 返回 hash 表中多个 field 的值
>hmget site google baidu
• hkeys key
– 返回 hash 表中所有 field 名称
>hmset site google www.g.cn baidu www.baidu.com
>hkeys site
- Hash 表操作(续 2 )
• hgetall key
1) "google"
2) "www.g.cn"
3) "baidu"
4) "www.baidu.com"
– 返回 hash 表中所有 field 的值
• hvals key
1) "www.g.cn"
2) "www.baidu.com"
– 返回 hash 表中所有 filed 的值
>hvals key
• hdel key field [field...]
– 删除 hash 表中多个 field 的值,不存在则忽略
>hdel site google baidu
List 列表
List 列表简介
• Redis 的 list 是一个字符队列
• 先进后出 注意:
• 一个 key 可以有多个值 正数,最后第一个往前输出
• lpush key value [value...] 负数,第一个往后输
– 将一个或多个值 value 插入到列表 key 的表头
– Key 不存在,则创建 key
>lpush list a b c //list1 值依次为 c b a
等同于 lpush list a; lpush list b; lpush list c
• lrange key start stop
– 从开始位置读取 key 的值到 stop 结束
>lrange list 0 2 // 从 0 位开始,读到 2 位为止
>lrange list 0 -1 // 从开始读到结束为止 ,输出到最后第一个输出的值
>lrange list 0 -2 // 从开始读到倒数第 2 位值,到最开始第一个不输出
>type list //列表类型
- List 列表操作(续 1 )
• lpop key
– 移除并返回列表头元素数据, key 不存在则返回 nil
>lpop list // 删除表头元素,可以多次执行
• llen key
– 返回列表 key 的长度
- List 列表操作(续 2 )
• lindex key index
– 返回列表中第 index 个值
如 lindex key 0 ; lindex key 2; lindex key -2
• lset key index value
– 将 key 中 index 位置的值修改为 value
>lset list 3 test // 将 list 中第 3 个值修改为 test
- List 列表操作(续 3 )
• rpush key value [value...]
– 将 value 插入到 key 的末尾
>rpush list3 a b c //list3 值为 a b c
>rpush list3 d // 末尾插入 d
• rpop key
– 删除并返回 key 末尾的值
– >rpush list3 a b c //list3 值为 a b c
>rpush list3 d // 末尾插入 d
其他操作
其他操作指令
• del key [key...]
– 删除一个或多个 key
• exists key
– 测试一个 key 是否存在
• expire key seconds
– 设置 key 的生存周期
• persist key
– 设置 key 永不过期
• ttl key
– 查看 key 的生存周期
- 其他操作指令(续 1 )
• keys 匹配
– 找符合匹配条件的 key ,特殊符号用 \ 屏蔽
>keys * // 显示所有 key
>keys h?llo // 匹配 hello,hallo,hxllo 等
>keys h*llo // 匹配 hllo 或 heeello 等
>keys h[ae]lo // 匹配 hello 和 hallo
• flushall
– 清空所有数据
• select id
– 选择数据库, id 用数字指定,默认数据库为 0
>select 0
>select 2
- 其他操作指令(续 2 )
• move key db_id
– 将当前数据库的 key 移动到 db_id 数据库中
>move key 1 // 将 key 移动到 1 数据库中
• rename key newkey
– 给 key 改名为 newkey , newkey 已存在时,则覆盖其值
• renamenx key newkey
– 仅当 newkey 不存在时,才将 key 改名为 newkey
- 其他操作指令(续 3 )
• sort key
– 对 key 进行排序
>lpush cost 1 8 7 2 5
>sort cost // 默认对数字排序,升序
>sort cost desc // 降序
>lpush test “about” “site” “rename”
>sort test alpha // 对字符排序
>sort cost alpha limit 0 3 // 排序后提取 0-3 位数据
>sort cost alpha limit 0 3 desc // 排序后提取倒数 0-3 位数据
>sort cost STORE cost2 // 对 cost 排序并保存为 cost2
• type key
– 返回 key 的数据类型
案例 3 :常用 Redis 数据库操作指令
• 对 Redis 数据库各数据类型进行增删改查操作
– 数据类型分别为 Strings 、 Hash 表、 List 列表
– 设置数据缓存时间
– 清空所有数据
– 对数据库操作
数据类型
数据类型总结
• 字符类型
• hash 表类型
• List 列表类型
管理命令
管理命令总结
• del key [key...]
– 删除一个或多个 key
• exists key
– 测试一个 key 是否存在
• expire key seconds
– 设置 key 的生存周期
• persist key
– 设置 key 永不过期
• ttl key
– 查看 key 的生存周期