对于Centos7在安装redis之前需要进行一些常用工具的安装:
sudo yum install net-tools 网络工具,比如ifconfig
sudo yum -y install lrzsz 文件的上传下载
关闭防火墙
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动
firewall-cmd --state #查看默认防火墙状态(关闭后显示notrunning,开启后显示running)
正式安装redis
使用命令的模式进行redis的安装(文件down到/usr/local/sftp/)
安装前需要进行tcl的安装,否则在make的时候报错
wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
tar -zxvf tcl8.6.1-src.tar.gz
cd /usr/local/tcl8.6.1/unix/
./configure
make && make install
使用redis-3.2.8.tar.gz(截止2017年4月的最新稳定版)
tar -zxvf redis-3.2.8.tar.gz
cd redis-3.2.8
make && make test && make install
在redis进行maketest时候会出现一系列的异常,有如下解决方案:
- You need tcl 8.5 or newer in order to run the Redis test
解决方案:前面已经安装了tcl;
用redis-server启动一下redis,做一些实验没什么意义。
要把redis作为一个系统的daemon进程去运行的,每次系统启动,redis进程一起启动,操作不走如下:
- redis utils目录下,有个redis_init_script脚本
redis-cli SHUTDOWN,连接本机的6379端口停止redis进程
redis-cli -h 127.0.0.1 -p 6379 SHUTDOWN,制定要连接的ip和端口号
redis-cli PING,ping redis的端口,看是否正常
redis-cli,进入交互式命令行
RDB和AOF是redis的一种数据持久化的机制。持久化是为了避免系统在发生灾难性的系统故障时导致的系统数据丢失。我们一般会将数据存放在本地磁盘,还会定期的将数据上传到云服务器。
RDB 是redis的snapshotting,通过redis.conf中的save配置进行设置,如 save 60 1000:
表示每隔60s,如果有超过1000个key发生了变更,那么就生成一个新的dump.rdb文件,就是当前redis内存中完整的数据快照,这个操作也被称之为snapshotting,也可以手动调用save或者bgsave命令,同步或异步执行rdb快照生成
AOF 是以appendonly方式进行数据的储存的,开启AOF模式后,所有存进redis内存的数据都会进入os cache中,然后默认1秒执行一次fsync写入追加到appendonly.aof文件中。一般我们配置redis.conf中的一下指令:
appendonly yes 可以打开AOF持久化机制,在生产环境里面,一般来说AOF都是要打开的;
appendfsync everysec 每秒将os cache中的数据fsync到磁盘,这个最常用的,生产环境一般都这么配置,性能很高,QPS可以上万;还有另外两种参数always和no,前者持续写入,性能低,数据保存完整,后者os cache自己控制写入时间,那样可能丢失数据很多;
rewrite策略:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
表示在第一次将缓存中的数据追加到aof文件中后记录次文件的大小,比如128MB,在追加数据到文件大小是上次文件的100%,也就是2倍,此时需要判断文件是否大于64mb,大于min-size则进行rewrite。
AOF和RDB模式我们一般在生产环境都会打开,一般而言,redis服务挂掉后进行重启会优先家在aof中的文件。
当启动一个slave node的时候,它会发送一个PSYNC命令给master node,如果这是slave node重新连接master node,那么master node仅仅会复制给slave部分缺少的数据;否则如果是slave node第一次连接master node,那么会触发一次full resynchronization;
开始full resynchronization的时候,master会启动一个后台线程,开始生成一份RDB快照文件,同时还会将从客户端收到的所有写命令缓存在内存中。RDB文件生成完毕之后,master会将这个RDB发送给slave,slave会先写入本地磁盘,然后再从本地磁盘加载到内存中。然后master会将内存中缓存的写命令发送给slave,slave也会同步这些数据。
slave node如果跟master node有网络故障,断开了连接,会自动重连。master如果发现有多个slave node都来重新连接,仅仅会启动一个rdb save操作,用一份数据服务所有slave node。
从redis 2.8开始,就支持主从复制的断点续传,如果主从复制过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份。
master node会在内存中常见一个backlog,master和slave都会保存一个replica offset还有一个master id,offset就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制,但是如果没有找到对应的offset,那么就会执行一次resynchronization。
master在内存中直接创建rdb,然后发送给slave,不会在自己本地落地磁盘了,可以有如下配置:
repl-diskless-sync
repl-diskless-sync-delay 等待一定时长再开始复制,因为要等更多slave重新连接过来
slave不会过期key,只会等待master过期key。如果master过期了一个key,或者通过LRU淘汰了一个key,那么会模拟一条del命令发送给slave。
- 打开slaveof参数
在slave node上配置:slaveof masterip masterport
- 集群监控,负责监控redis master和slave进程是否正常工作
min-slaves-to-write 3
min-slaves-max-lag 10
在redis.conf配置文件中,上面的参数代表至少需要3个slaves节点与master节点进行连接,并且master和每个slave的数据同步延迟不能超过10秒。一旦上面的设定没有匹配上,则master不在提供相应的服务。
sdown和odown两种失败状态:
sdown达成的条件很简单,如果一个哨兵ping一个master,超过了is-master-down-after-milliseconds指定的毫秒数之后,就主观认为master宕机
sdown到odown转换的条件很简单,如果一个哨兵在指定时间内,收到了quorum指定数量的其他哨兵也认为那个master是sdown了,那么就认为是odown了,客观认为master宕机
哨兵互相之间的发现,是通过redis的pub/sub系统实现的,每个哨兵都会往**sentinel:hello**这个channel里发送一个消息,这时候所有其他哨兵都可以消费到这个消息,并感知到其他的哨兵的存在。
每隔两秒钟,每个哨兵都会往自己监控的某个master+slaves对应的__sentinel__:hello channel里发送一个消息,内容是自己的host、ip和runid还有对这个master的监控配置。
每个哨兵也会去监听自己监控的每个master+slaves对应的__sentinel__:hello channel,然后去感知到同样在监听这个master+slaves的其他哨兵的存在。
每个哨兵还会跟其他哨兵交换对master的监控配置,互相进行监控配置的同步。
3.3 slave配置的自动纠正
哨兵会负责自动纠正slave的一些配置,比如slave如果要成为潜在的master候选人,哨兵会确保slave在复制现有master的数据;如果slave连接到了一个错误的master上,比如故障转移之后,那么哨兵会确保它们连接到正确的master上。
3.4 slave->master选举算法
如果一个master被认为odown了,而且majority哨兵都允许了主备切换,那么某个哨兵就会执行主备切换操作,此时首先要选举一个slave来作为新的master。
选举会考虑slave的一些信息
如果一个slave跟master断开连接已经超过了down-after-milliseconds的10倍,外加master宕机的时长,那么slave就被认为不适合选举为master
(down-after-milliseconds * 10) + milliseconds_since_master_is_in_SDOWN_state
接下来会对slave进行排序
每次一个哨兵要做主备切换,首先需要quorum数量的哨兵认为odown,然后选举出一个slave来做切换,这个slave还得得到majority哨兵的授权,才能正式执行切换;
如果quorum < majority,比如5个哨兵,majority就是3,quorum设置为2,那么就3个哨兵授权就可以执行切换;
但是如果quorum >= majority,那么必须quorum数量的哨兵都授权,比如5个哨兵,quorum是5,那么必须5个哨兵都同意授权,才能执行切换
哨兵会对一套redis master+slave进行监控,有相应的监控的配置,执行切换的那个哨兵,会从要切换到的新master(salve->master)那里得到一个configuration epoch,这就是一个version号,每次切换的version号都必须是唯一的.
如果第一个选举出的哨兵切换失败了,那么其他哨兵,会等待failover-timeout时间,然后接替继续执行切换,此时会重新获取一个新的configuration epoch,作为新的version号。
哨兵完成切换之后,会在自己本地更新生成最新的master配置,然后同步给其他的哨兵,就是通过之前说的pub/sub消息机制
这里之前的version号就很重要了,因为各种消息都是通过一个channel去发布和监听的,所以一个哨兵完成一次新的切换之后,新的master配置是跟着新的version号的,其他的哨兵都是根据版本号的大小来更新自己的master配置的。
- 创建如下文件夹
mkdir /etc/sentinal
mkdir -p /var/sentinal/5000
- 启动哨兵client端
redis-cli -h 192.168.xxx.xxx -p 5000
增加sentinal,会自动发现;
删除sentinal的步骤:
(1)停止sentinal进程
(2)SENTINEL RESET *,在所有sentinal上执行,清理所有的master状态
(3)SENTINEL MASTER mastername,在所有sentinal上执行,查看所有sentinal对数量是否达成了一致
4.3.2 slave的永久下线
让master摘除某个已经下线的slave:SENTINEL RESET mastername,在所有的哨兵上面执行.
redis的集群模式为了解决系统的横向扩展以及海量数据的存储问题,如果你的数据量很大,那么就可以用redis cluster。
redis cluster可以支撑N个redis master,一个master上面可以挂载多个slave,一般情况我门挂载一个到两个slave,master在挂掉以后会主动切换到slave上面,或者当一个master上面的slave都挂掉后,集群会从其他master上面找到冗余的slave挂载到这个master上面,达到了系统的高可用性。
redis cluster有固定的16384个hash slot,对每个key计算CRC16值,然后对16384取模,可以获取key对应的hash slot;
redis cluster中每个master都会持有部分slot,比如有3个master,那么可能每个master持有5000多个hash slot;
hash slot让node的增加和移除很简单,增加一个master,就将其他master的hash slot移动部分过去,减少一个master,就将它的hash slot移动到其他master上去,移动hash slot的成本非常低;
2.1 redis cluster的重要配置
cluster-enabled
cluster-config-file :这是指定一个文件,供cluster模式下的redis实例将集群状态保存在那里,包括集群中其他机器的信息,比如节点的上线和下限,故障转移,不是我们去维护的,给它指定一个文件,让redis自己去维护.
cluster-node-timeout :节点存活超时时长,超过一定时长,认为节点宕机,master宕机的话就会触发主备切换,slave宕机就不会提供服务.
2.2 在三台机器上启动6个redis实例
修改redis.conf配置文件
mkdir -p /etc/redis-cluster
mkdir -p /var/log/redis
mkdir -p /var/redis/7001
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.xxx.xxx
appendonly yes
将上面的配置文件,在/etc/redis下放6个,分别为: 7001.conf,7002.conf,7003.conf,7004.conf,7005.conf,7006.conf
在/etc/init.d下,放6个启动脚本,分别为: redis_7001, redis_7002, redis_7003, redis_7004, redis_7005, redis_7006
每个启动脚本内,都修改对应的端口号
将每个配置文件中的slaveof给删除(不要开启从节点配置)
2.3 创建集群
使用如下命令时报错
yum install -y ruby
yum install -y rubygems
gem install redis
redis requires Ruby version >= 2.2.2的报错,查了资料发现是Centos默认支持ruby到2.0.0,可gem 安装redis需要最低是2.2.2
解决办法是 先安装rvm,再把ruby版本提升至2.3.3
sudo yum install curl
gpg2 --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3
curl -L get.rvm.io | bash -s stable
find / -name rvm -print
source /usr/local/rvm/scripts/rvm
rvm list known
rvm install 2.3.4
rvm use 2.3.4 --default
rvm remove 2.0.0
ruby --version
gem install redis
使用redis-trib.rb命令创建集群
cp /usr/local/sftp/redis-3.2.8/src/redis-trib.rb /usr/local/bin
redis-trib.rb create --replicas 1 192.168.199.141:7001 192.168.199.141:7002 192.168.199.142:7003 192.168.199.142:7004 192.168.199.143:7005 192.168.199.143:7006
–replicas: 表示每个master有几个slave
redis-trib.rb check 192.168.31.187:7001 查看状体
3.1 加入新master
mkdir -p /var/redis/7007
port 7007
cluster-enabled yes
cluster-config-file /etc/redis-cluster/node-7007.conf
cluster-node-timeout 15000
daemonize yes
pidfile /var/run/redis_7007.pid
dir /var/redis/7007
logfile /var/log/redis/7007.log
bind 192.168.199.144
appendonly yes
以上相同配置完成后,设置启动脚本进行启动;然后用如下命令进行node节点添加:
redis-trib.rb add-node 192.168.199.144:7007 192.168.199.141:7001
redis-trib.rb check 192.168.199.141:7001
3.2 reshard一些数据过去
resharding的意思就是把一部分hash slot从一些node上迁移到另外一些node上
redis-trib.rb reshard 192.168.199.141:7001
3.3 添加node作为slave
进行上面的相同配置后,设定启动脚本,执行如下命令(其中masterid可以通过check命令进行查看):
redis-trib.rb add-node --slave --master-id 28927912ea0d59f6b790a50cf606602a5ee48108 192.168.199.144:7008 192.168.199.141:7001
3.4 删除node
先用resharding将数据都移除到其他节点,确保node为空之后,才能执行remove操作
redis-trib.rb del-node 192.168.199.141:7001 bd5a40a6ddccbd46a0f4a2208eb25d2453c2a8db