wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
tar -xzvf tcl8.6.1-src.tar.gz
cd /usr/local/tcl8.6.1/unix/
./configure
make && make install
tar -zxvf redis-3.2.8.tar.gz
cd redis-3.2.8
make && make test && make install
daemonize yes 【让redis以daemon进程运行】
pidfile /var/run/redis_6379.pid 【设置redis的pid文件位置】
port 6379 【设置redis的监听端口号】
dir /var/redis/6379 【 设置持久化文件的存储位置】
在redis_6379脚本中,最上面,加入两行注释
# chkconfig: 2345 90 10
# description: Redis is a persistent key-value database
chkconfig redis_6379 on
redis-cli SHUTDOWN 【连接本机的6379 端口停止redis进程】
redis-cli -h 127.0.0.1 -p 6379 SHUTDOWN 【制定要连接的ip和端口号】
redis-cli PING 【ping redis 的端口,看是否正常】
redis-cli 【进入交互式命令行】
SET test abcd 【简单测试】
GET test
修改配置文件【redis.conf】 文件,本次案例中也就是【/etc/redis/6379.conf】,去配置持久化;
save 60 1000
含义:每隔60s 如果有超过1000个key发生了变更,那么就生成一个新的dump.rdb文件,就是当前redis内存中完整的数据快照,这个操作也被称之为snapshotting - 快照
或者 也可以手动调用save或者bgsave命令,同步或异步执行rdb快照生成
save可以设置多个,就是多个snapshotting检查点,每到一个检查点,就会去check一下,是否有指定的key数量发生了变更,如果有,就生成一个新的dump.rdb文件 如下:
save 600 5
save 300 10
save 30 20
dump.rdb,每次生成一个新的快照,都会覆盖之前的老快照
(1)在redis中保存几条数据,立即停掉redis进程然后重启redis,看看刚才插入的数据还在不在
(2)通过redis-cli SHUTDOWN这种方式去停掉redis,其实是一种安全退出的模式
redis在退出的时候会将内存中的数据立即生成一份完整的rdb快照【/var/redis/6379/dump.rdb】
(3)在redis中再保存几条新的数据,用kill -9粗暴杀死redis进程,模拟redis故障异常退出,导致内
存数据丢失的场景;这次就发现redis进程异常被杀掉,数据没有进dump文件,几条最新的数据就 丢失了
(4)手动设置一个save检查点,save 5 1
(5)写入几条数据,等待5秒钟,会发现自动进行了一次dump rdb快照,并且在dump.rdb中发现了数据
(6)异常停掉redis进程,再重新启动redis,看刚才插入的数据还在
AOF持久化,默认是关闭的,redis默认打开的持久化方式是 RDB 生产环境中一般启用AOF持久化策略;
修改配置文件【redis.conf】 文件,本次案例中也就是【/etc/redis/6379.conf】,去配置持久化;
appendonly yes
打开AOF持久化机制之后,redis每次接收到一条写命令,就会写入日志文件中,当然是先写入os cache的,然后每隔一定时间再fsync一下
配置AOF的fsync策略,有三种策略可以选择,一种是每次写入一条数据就执行一次fsync; 一种是每隔一秒执行一次fsync; 一种是不主动执行fsync;
always: 每次写入一条数据,立即将这个数据对应的写日志fsync到磁盘上去,性能非常非常差,吞吐量很低; 【如果要确保redis里的数据一条都不丢,那就只能选择该模式了】
everysec: 每秒将os cache中的数据fsync到磁盘,这个最常用的,生产环境一般都这么配置,性能很高,QPS还是可以上万的;
no: 仅仅redis负责将数据写入os cache就撒手不管了,然后后面os自己会时不时有自己的策略将数据刷入磁盘 该方式就不可控了;
比如日志里已经存放了针对100w数据的写日志了; redis内存只剩下10万; 基于内存中当前的10万数据构建一套最新的日志,到AOF中; 覆盖之前的老日志; 确保AOF日志文件不会过大,保持跟redis内存数据量一致
在redis.conf中,可以配置rewrite策略 本次案例中也就是【/etc/redis/6379.conf】
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
比如说上一次AOF rewrite操作之后,是 持久化文件是128mb
以上两个条件必须满足才做 rewrite操作
rewrite的工作流程
备注:redis 2.4之前,还需要手动,开发一些脚本,crontab,通过BGREWRITEAOF命令去执行AOF rewrite,但是redis 2.4之后,会自动进行rewrite操作
如果redis在append数据到AOF文件时,机器宕机了,可能会导致AOF文件破损
用 redis-check-aof --fix ***.aof 命令来修复破损的AOF文件
小实验:
(1)在有rdb的dump和aof的appendonly的同时,rdb里也有部分数据,aof里也有部分数据,这个时候其实会发现,rdb的数据不会恢复到内存中
(2)我们模拟让aof破损,然后fix,有一条数据会被fix删除
(3)再次用fix得aof文件去重启redis,发现数据只剩下一条了
总结:数据恢复完全是依赖于底层的磁盘的持久化的,如果 rdb 和 aof 持久化文件上都没有数据了,那Redis启动后就没数据了
数据备份方案
0 * * * * sh /usr/local/redis/copy/redis_rdb_copy_hourly.sh
#!/bin/sh
cur_date=`date +%Y%m%d%k`
rm -rf /usr/local/redis/snapshotting/$cur_date
mkdir /usr/local/redis/snapshotting/$cur_date
cp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date
del_date=`date -d -48hour +%Y%m%d%k`
rm -rf /usr/local/redis/snapshotting/$del_date
0 0 * * * sh /usr/local/redis/copy/redis_rdb_copy_daily.sh
#!/bin/sh
cur_date=`date +%Y%m%d`
rm -rf /usr/local/redis/snapshotting/$cur_date
mkdir /usr/local/redis/snapshotting/$cur_date
cp /var/redis/6379/dump.rdb /usr/local/redis/snapshotting/$cur_date
del_date=`date -d -1month +%Y%m%d`
rm -rf /usr/local/redis/snapshotting/$del_date
数据恢复方案
在数据安全丢失的情况下,基于rdb冷备,如何完美的恢复数据,同时还保持aof和rdb的双开?
停止redis,关闭aof,拷贝rdb备份,重启redis,确认数据恢复,
直接在命令行热修改redis配置-打开aof [ config set appendonly yes ]
这个redis就会将内存中的数据对应的日志,写入aof文件中
此时aof和rdb两份数据文件的数据就同步了;
热修改配置参数后配置文件中的实际的参数没有被持久化的修改,
需要再次停止redis,手动修改配置文件打开aof的命令 [ appendonly yes ]
再次重启redis
进入redis查看参数是否生效:config get appendonly
单机的redis几乎不太可能说QPS超过10万+,除非一些特殊情况,比如你的机器性能特别好,
配置特别高,物理机维护做的特别好,而且你的整体的操作不是太复杂;
对缓存而言一般都是用来支撑读高并发的,写的请求相对是比较少的,所以采用读写分离的方式可以有效地提升redis的插叙性能;
具体方式:
1.主从架构(支持水平扩容) -> 读写分离 -> 支撑10万+读QPS的架构 [主节点-写操作,从节点-读操作]
但是目前 Java客户端 jedis 对读写分离这块支持不是很好,需要修改底层源码方可实现-较为复杂;
2.多master多slave 通过Redis的 hash slot算法将数据分片存储(分布式) master也可以水平扩容(真实环境一般是该方式);
其实目前所有的读跟写操作都是在master上进行的---期待后续jedis的改进;
redis-benchmark 是 redis自己提供的压测工具,是最快捷最方便的,当然这个工具比较简单用与简单的操作和场景去压测;
redis-3.2.8/src 进入redis安装目录
./redis-benchmark -h 192.168.31.187 执行命令
命令参数如下
-c Number of parallel connections (default 50) 用户量
-n Total number of requests (default 100000) 请求量
-d Data size of SET/GET value in bytes (default 2) value数据大小
QPS的两个杀手:一个是复杂操作(lrange 等);二是 value值很大;
redis replication -> 主从架构 -> 读写分离 -> 水平扩容支撑读高并发;
master持久化对于主从架构的安全保障的意义
master -> RDB和AOF都关闭了 ->数据全部在内存中
master宕机,重启,是没有本地数据可以恢复的,然后就会直接认为自己的数据是空的
master就会将空的数据集同步到slave上去,所有slave的数据全部清空
100%的数据丢失
所以:master节点,必须要使用持久化机制
Redis中的主从切换是由 sentinal 中文名是哨兵 实现的
哨兵是Redis集群架构中非常重要的一个组件,主要功能如下
哨兵本身也是分布式的,作为一个哨兵集群去运行,互相协同工作
哨兵的核心知识
哨兵集群必须部署2个以上节点 ; 如果哨兵集群仅仅部署了个2个哨兵实例 故障转移不会执行;
主备切换数据丢失主要是由两种情况造成的:异步复制导致的数据丢失、脑裂导致的数据丢失
(1)异步复制导致的数据丢失
因为master -> slave的复制是异步的,所以可能有部分数据还没复制到slave,master就宕机了,此时这些部分数据就丢失了;
(2)脑裂导致的数据丢失
脑裂--也就是说,某个master所在机器突然脱离了正常的网络,跟其他slave机器不能连接,但是实际上master还运行着
此时哨兵(sentinal node)可能就会认为master宕机了,然后开启选举,将其他slave切换成了master;
这个时候,集群里就会有两个master,也就是所谓的脑裂
此时虽然某个slave被切换成了master,但是可能client还没来得及切换到新的master,还继续写向旧master的数据可能也丢失了
因此旧master再次恢复的时候,会被作为一个slave挂到新的master上去,自己的数据会清空,重新从新的master复制数据;
解决方案:修改redis config 配置参数
min-slaves-to-write 1
min-slaves-max-lag 10
#含义:要求至少有1个slave,数据复制和同步的延迟不能超过10秒
如果说一旦所有的slave,数据复制和同步的延迟都超过了10秒钟,
那么这个时候 [master就不会再接收任何请求了]
上面两个配置可以减少异步复制和脑裂导致的数据丢失
(1)减少异步复制的数据丢失
有了min-slaves-max-lag这个配置,就可以确保说,一旦slave复制数据和ack延时太长,就认为可能master宕机后损失的数据太多了,那么就拒绝写请求,这样可以把master宕机时由于部分数据未同步到slave导致的数据丢失降低的可控范围内
(2)减少脑裂的数据丢失
如果一个master出现了脑裂,跟其他slave丢了连接,那么上面两个配置可以确保说,如果不能继续给指定数量的slave发送数据,而且slave超过10秒没有给自己ack消息,那么就直接拒绝客户端的写请求
当master不再接受新的请求时:应用需要做 服务降级、应用限流、采用消息队列访问redis等操作;
哨兵的配置文件 在 redis的 sentinel.conf 文件中
每一个哨兵都可以去监控多个maser-slaves的主从架构(下面这段配置就监控了两个master node)
#被监控者 1
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 60000
sentinel failover-timeout mymaster 180000
sentinel parallel-syncs mymaster 1
#被监控者 2
sentinel monitor resque 192.168.1.3 6380 4
sentinel down-after-milliseconds resque 10000
sentinel failover-timeout resque 180000
sentinel parallel-syncs resque 5
这是最小的哨兵配置如果发生了master-slave故障转移,或者新的哨兵进程加入哨兵集群,那么哨兵会自动更新自己的配置文件
sentinel monitor mymaster 127.0.0.1 6379 2
解释如下: mymaster 节点的名称;127.0.0.1 当前节点的IP;6379 当前节点的端口;2:quorum;
quorum的解释如下:
sentinel down-after-milliseconds mymaster 60000
down-after-milliseconds,超过多少毫秒跟一个redis实例断了连接,哨兵就可能认为这个redis实例挂了
sentinel parallel-syncs mymaster 1
parallel-syncs:新的master别切换之后同时有多少个slave被切换到去连接新master重新做同步,数字越低,花费的时间越多
假设你的redis是1个master,4个slave;然后master宕机了,4个slave中有1个切换成了master,剩下3个slave就要挂到新的master上面去;这个时候,如果parallel-syncs是1,那么3个slave会一个一个地挂接到新的master上面去;1个挂接完并且从新的master sync完数据之后,再挂接下一个;如果parallel-syncs是3,那么一次性就会把所有slave挂接到新的master上去
sentinel failover-timeout mymaster 180000
failover-timeout,执行故障转移的timeout超时时长
sentinel 部署
#创建目录存放配置文件 mkdir /etc/sentinal
#创建目录存在数据文件 mkdir -p /var/sentinal/5000
#复制sentinal.conf 文件内容到 5000.conf文件并放到该目录 /etc/sentinel/5000.conf
#第一台机器的配置
port 5000 #使用端口号
bind 192.168.31.187 #本机IP
dir /var/sentinal/5000 #数据文件存放目录
sentinel monitor mymaster 192.168.31.187 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
#第二台机器的配置
port 5000
bind 192.168.31.19
dir /var/sentinal/5000
sentinel monitor mymaster 192.168.31.187 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
#第三台机器的配置
port 5000
bind 192.168.31.227
dir /var/sentinal/5000
sentinel monitor mymaster 192.168.31.187 6379 2
sentinel down-after-milliseconds mymaster 30000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1
redis cluster的重要配置 (其实是Redis通过 hash slot 算法将数据路由到不同的Master上[数据分片])
搭建案例:
#redis cluster集群要求至少3个master去组成一个高可用健壮的分布式的集群;
#每个master都建议至少给一个slave;3个master,3个slave是最少的要求;
#要保证,每个master都跟自己的slave不在同一台机器上;
#3台机器去搭建6个redis实例的redis cluster 配置如下-已一台配置为例子(其他的都修改端口相关配置)
创建目录:mkdir -p /etc/redis-cluster #集群配置文件
创建目录:mkdir -p /var/log/redis #日志文件
创建目录:mkdir -p /var/redis/7001 #端口用7001,其他5个分别为 7002,7003,7004,7005,7006;
以下为配置文件:/etc/redis/7001.conf 的相关参数
port 7001
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7001.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7001.pid
dir /var/redis/7001
logfile /var/log/redis/7001.log
bind 192.168.31.187
appendonly yes
# 准备生产环境的启动脚本
在/etc/init.d下,放6个启动脚本;
分别为: redis_7001, redis_7002, redis_7003, redis_7004, redis_7005, redis_7006
每个启动脚本内,都修改对应的端口号
启动的时候 在 init.d 目录下 执行 ./redis_7001 start 即可启动
#分别在3台机器上,启动6个redis实例
# 创建集群
#其中一台机器先安装以下工具
yum install -y ruby
yum install -y rubygems
gem install redis
cp /usr/local/redis-3.2.8/src/redis-trib.rb /usr/local/bin
redis-trib.rb create --replicas 1 192.168.31.187:7001 192.168.31.187:7002 192.168.31.19:7003 192.168.31.19:7004 192.168.31.227:7005 192.168.31.227:7006
#以上创建集群过程中 IP及端口号不能写错;
#以上操作在其中一台机器中安装即可 ;
--replicas 含义: 每个master有几个slave (咱们这里只有一台就写 1 )
到此结束:我们6台机器;3个master;3个slave,尽量自己让master和slave不在一台机器上
redis-trib.rb check 192.168.31.187:7001 【可以用该命令检查集群配置情况】
在slave查数据的方式
方式1:在这个redis cluster中,如果你要在slave读取数据,那么需要先执行 readonl y指令
然后再执行查询操作 : get mykey1
方式2:用 redis-cli -c启动;如:redis-cli -h 192.168.31.187 -p 7001 -c
加上 -c 就会自动进行各种底层的重定向的操作
实验redis cluster的读写分离的时候,会发现有一定的限制性,默认情况下,redis cluster的核心的理念,主要是用slave做高可用的,每个master挂一两个slave,主要是做数据的热备,还有master故障时的主备切换,实现高可用的
redis cluster默认是不支持slave节点读或者写的,跟我们手动基于replication搭建的主从架构不一样的
进入Redis控制台执行:info replication 可以查看当前Redis节点信息
redis扩容,缩容
1、加入新master
例如:手动启动一个新的redis实例,在7007端口上
redis-trib.rb add-node 192.168.31.227:7007 192.168.31.187:7001
#检查集群状态
redis-trib.rb check 192.168.31.187:7001
2、reshard一些数据过去
resharding的意思就是把一部分hash slot从一些node上迁移到另外一些node上
redis-trib.rb reshard 192.168.31.187:7001 (按照提示操作数据源,有好几个,填写完后写 down)
要把之前3个master上,总共4096个hashslot迁移到新的第四个master上去
会提示以下信息:
How many slots do you want to move (from 1 to 16384)?
(此次用计算器计算一下保险点儿 - 确保每个 master 上的slot要均匀 )
3、添加node作为slave
命令如下:
redis-trib.rb add-node --slave --master-id {添加到那个master的id} {要被添加的IP端口} {集群中第一个master的IP端口}
如:redis-trib.rb add-node --slave --master-id 28927912ea0d59f6b790a50cf606602a5ee48108 192.168.31.227:7008 192.168.31.187:7001
4、删除node
先用resharding将数据都移除到其他节点,确保node为空之后,才能执行remove操作
//确保 每个 master 上的slot要均匀
redis-trib.rb reshard 192.168.31.187:7001
当你清空了一个master的hashslot时,redis cluster就会自动将其slave挂载到其他master上去
这个时候就只要删除掉master就可以了
redis-trib.rb del-node 192.168.31.187:7001 bd5a40a6ddccbd46a0f4a2208eb25d2453c2a8db
slave的自动迁移
比如现在有10个master每个有1个slave,然后新增了3个slave作为冗余,有的master就有2个slave了,有的master出现了salve冗余;
这时如果某个master的slave挂了,那么redis cluster会自动迁移一个冗余的slave给那个master,确保master高可用;
该方式只要多加一些冗余的slave就可以了实现了;