您的位置:首页 > 数据库 > Redis

redis的安装配置及其基于sentinel的redis集群高可用方案

2014-10-28 20:31 1191 查看
大纲

一、前言

二、NoSQL简介
三、redis的使用场景
四、Redis Sentinel介绍

五、redis的安装配置详解

六、基于sentinel的redis集群高可用方案的实现

七、基于sentinel内置功能对redis进行监控报警机制的实现

八、使用zabbix监控redis

九、通过定时任务的执行监控redis的健康状态

一、前言 本文主要介绍redis安装配置的过程,以及通过sentinel实现redis集群的高可用方案,还会介绍一下通过sentinel自身所提供的功能进行异常检测并在必要的时候飞信通知系统管理员,最后会提一下使用zabbix监控redis的实现方法。
在网上搜了两天,一直没找到合适的文档或者是博客,今天把这几天的成果写成博客,希望能帮助到大家,当然,本人也是菜鸟一枚,所以,有些不足之处大家也不要见笑。二、NoSQL简介
1、什么是NoSQL

NoSQL,指的是非关系型的数据库。NoSQL有时也称作Not Only SQL的缩写,是对不同于传统的关系型数据库的数据库管理系统的统称。
NoSQL用于超大规模数据的存储。(例如谷歌或Facebook每天为他们的用户收集万亿比特的数据)。这些类型的数据存储不需要固定的模式,无需多余操作就可以横向扩展。
2、RDBMS VS NoSQL

关系型数据库遵循ACID规则
事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性:
①、A (Atomicity) 原子性
原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚。
比如银行转账,从A账户转100元至B账户,分为两个步骤:1)从A账户取100元;2)存入100元至B账户。这两步要么一起完成,要么一起不完成,如果只完成第一步,第二步失败,钱会莫名其妙少了100元。
②、C (Consistency) 一致性
一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。
例如现有完整性约束a+b=10,如果一个事务改变了a,那么必须得改变b,使得事务结束后依然满足a+b=10,否则事务失败。
③、I (Isolation) 独立性
所谓的独立性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。
比如现有有个交易是从A账户转100元至B账户,在这个交易还未完成的情况下,如果此时B查询自己的账户,是看不到新增加的100元的。
④、D (Durability) 持久性
持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。
RDBMS
- 高度组织化结构化数据
- 结构化查询语言(SQL) (SQL)
- 数据和关系都存储在单独的表中。
- 数据操纵语言,数据定义语言
- 严格的一致性
- 基础事务

NoSQL
- 代表着不仅仅是SQL
- 没有声明性查询语言
- 没有预定义的模式
-键 - 值对存储,列存储,文档存储,图形数据库
- 最终一致性,而非ACID属性
- 非结构化和不可预知的数据
- CAP定理
- 高性能,高可用性和可伸缩性
NoSQL的优点/缺点
优点:
- 高可扩展性
- 分布式计算
- 低成本
- 架构的灵活性,半结构化数据
- 没有复杂的关系
缺点:
- 没有标准化
- 有限的查询功能(到目前为止)
- 最终一致是不直观的程序

三、redis的使用场景
1.取最新N个数据的操作
2.排行榜应用,取TOP N操作
3.需要精准设定过期时间的应用
4.计数器应用
5.Uniq操作,获取某段时间所有数据排重值
6.实时系统,反垃圾系统
7.Pub/Sub构建实时消息系统
8.构建队列系统
9.缓存
详见 http://blog.nosqlfan.com/html/2235.html
四、Redis Sentinel介绍
Redis Sentinel是Redis官方提供的集群管理工具,主要有三大功能:
◆监控,能持续监控Redis的主从实例是否正常工作;
◆通知,当被监控的Redis实例出问题时,能通过API通知系统管理员或其他程序;
◆自动故障恢复,如果主实例无法正常工作,Sentinel将启动故障恢复机制把一个从实例提升为主实例,其他的从实例将会被重新配置到新的主实例,且应用程序会得到一个更换新地址的通知。
Redis Sentinel是一个分布式系统,可以部署多个Sentinel实例来监控同一组Redis实例,它们通过Gossip协议来确定一个主实例宕机,通过Agreement协议来执行故障恢复和配置变更,一般在生产环境中部署多个实例来提高系统可用性,只要有一个Sentinel实例运行正常,就能保证被监控的Redis实例运行正常(类似Zookeeper,通过多个Zookeeper来提高系统可用性);

五、redis的安装配置详解
采用Redis的版本号:redis-2.8.17.tar.gz
http://download.redis.io/releases/redis-2.8.17.tar.gz
1、redis的安装方式很简单,直接make就行:
[root@vm_101 ~]# tar xf redis-2.8.17.tar.gz
[root@vm_101 ~]# cd redis-2.8.17
[root@vm_101 redis-2.8.17]# ls
00-RELEASENOTES  CONTRIBUTING  deps     Makefile   README      runtest           sentinel.conf  tests
BUGS   COPYING       INSTALL  MANIFESTO  redis.conf  runtest-sentinel  src   utils
[root@vm_101 redis-2.8.17]# ls src/ | grep [^cho]$
Makefile
Makefile.dep
valgrind.sup
[root@vm_101 ~]# make
[root@vm_101 redis-2.8.17]# ls src/ | grep [^cho]$   #可以看的出make之后生成了这么多的文件
Makefile
Makefile.dep
redis-benchmark
redis-check-aof
redis-check-dump
redis-cli
redis-sentinel
redis-server
valgrind.sup
[root@vm_101 redis-2.8.17]# mkdir /opt/redis/{etc,bin,init.d} -pv
mkdir: created directory `/opt/redis'
mkdir: created directory `/opt/redis/etc'
mkdir: created directory `/opt/redis/bin'
mkdir: created directory `/opt/redis/init.d'
[root@vm_101 redis-2.8.17]# cp utils/redis_init_script /opt/redis/init.d/  #启动脚本
[root@vm_101 redis-2.8.17]# cp redis.conf sentinel.conf /opt/redis/etc/  #配置文件的模板
[root@vm_101 src]# cp redis-benchmark redis-check-aof redis-check-dump redis-cli \
redis-server redis-sentinel /opt/redis/bin/ #二进制程序文件


二进制文件说明:
redis-server:Redis服务器的daemon启动程序
redis-sentinel:Redis sentinel服务的daemon启动程序,等同于"redis-server --sentinel"
redis-cli:Redis命令行操作工具。当然,你也可以用telnet根据其纯文本协议来操作
redis-benchmark:Redis性能测试工具,测试Redis在你的系统及你的配置下的读写性能
redis-check-aof:更新日志检查
redis-check-dump:用于本地数据库检查
2、redis的配置文件redis.conf各选项详解:

见附件:redis.conf.txt

3、为redis提供启动配置文件

daemonize yes
pidfile /var/run/redis_6379.pid
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 0
loglevel notice
logfile "/var/log/redis/redis_6379.log"
databases 16
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir ./
slave-serve-stale-data yes
slave-read-only yes
repl-disable-tcp-nodelay no
slave-priority 100
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
aof-rewrite-incremental-fsync yes
创建redis的日志目录:

[root@vm_101 etc]# mkdir /var/log/redis
在/opt/redis/init.d/redis_init_script中修改相应的变量即可
#!/bin/sh
#
# Simple Redis init.d script conceived to work on Linux systems
# as it does use of the /proc filesystem.
REDISPORT=6379
EXEC=/opt/redis/bin/redis-server
CLIEXEC=/opt/redis/bin/redis-cli
PIDFILE=/var/run/redis/redis_${REDISPORT}.pid
CONF="/opt/redis/etc/redis_${REDISPORT}.conf"
case "$1" in
start)
if [ -f $PIDFILE ]
then
echo "$PIDFILE exists, process is already running or crashed"
else
echo "Starting Redis server..."
$EXEC $CONF
fi
;;
stop)
if [ ! -f $PIDFILE ]
then
echo "$PIDFILE does not exist, process is not running"
else
PID=$(cat $PIDFILE)
echo "Stopping ..."
$CLIEXEC -p $REDISPORT shutdown
while [ -x /proc/${PID} ]
do
echo "Waiting for Redis to shutdown ..."
sleep 1
done
echo "Redis stopped"
fi
;;
*)
echo "Please use start or stop as first argument"
;;
esac
[root@vm_101 etc]# cp /opt/redis/init.d/redis_init_script /etc/init.d/redis
[root@vm_101 etc]# /etc/init.d/redis start
Starting Redis server...
[root@vm_101 etc]# netstat -tunlp | grep 6379
tcp        0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN      6027/redis-server *
tcp        0      0 :::6379                     :::*                        LISTEN      6027/redis-server *
[root@vm_101 etc]# ps aux | grep redis
root      6027  0.0  0.0  95304  1852 ?        Ssl  18:09   0:00 /opt/redis/bin/redis-server *:6379
root      6048  0.0  0.0  61188   740 pts/0    R+   18:16   0:00 grep redis
连接到redis上测试一下:

[root@vm_101 etc]# /opt/redis/bin/redis-cli
127.0.0.1:6379> set test test
OK
127.0.0.1:6379> get test
"test"


六、基于sentinel的redis集群高可用方案的实现
实验在三台主机的进行,每台主机布置一个redis服务和一个sentinel服务

server1:192.168.111.19 # master
server2:192.168.111.12 # slave
server3:192.168.111.21 # slave

server1中redis的配置文件:

daemonize yes
pidfile "/var/run/redis.pid"
bind 127.0.0.1 192.168.111.19
port 6000
timeout 0
databases 16
loglevel notice
logfile "/var/log/redis/redis.log"
save 86400 10
rdbcompression yes
dbfilename "dump.rdb"
dir "/opt/redis"
slave-serve-stale-data yes
repl-ping-slave-period 10
repl-timeout 60
slave-priority 100
masterauth redis123456
requirepass "redis123456"
maxclients 10000
maxmemory 4GB
maxmemory-policy noeviction
appendonly no
appendfsync everysec
no-appendfsync-on-rewrite yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
slowlog-log-slower-than 10000
slowlog-max-len 128
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
activerehashing yes


server2与server3中redis的配置文件可根据上述配置文件进行适当的调整,主要是:
slaveof 192.168.111.19 6000 ##必须添加进去的一行
相对应的IP地址也要做出调整,另外生产环境中可根据各个主机的性能对内存等参数做出一些调整

sentinel的配置文件详解:见附件:sentinel.conf.txt

为server1提供sentinel提供配置文件:
port 26000
dir "/opt/redis/etc"
sentinel monitor master_status 192.168.111.19 6000 1
sentinel down-after-milliseconds master_status 60000
sentinel auth-pass master_status hz6d53kf12x.,222
sentinel config-epoch master_status 0
sentinel notification-script mymaster /opt/redis/notify.sh
sentinel client-reconfig-script mymaster /opt/redis/reconfig.sh
bind 192.168.111.19


server2,server3修改最后一行,将IP改为自身的IP即可
为sentinel提供启动脚本
#!/bin/bash
### BEGIN INIT INFO
# Provides:          redis sentinel
# Required-Start:    $all
# Required-Stop:    $all
# Default-Start:    2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Starts redis sentinel
# Description:      Starts redis sentinel using start-stop-daemon
### END INIT INFO

NAME=redis-sentinel
BIN=/opt/redis/bin/redis-server
CONF=/opt/redis/etc/sentinel.conf
SENTINEL_PID=/var/run/redis-sentinel.pid
LOG=/var/log/redis/redis-sentinel.log
CMD=$1

start() {
echo "Starting $NAME ..."
$BIN $CONF --sentinel >> $LOG 2>&1 &
echo $! > "${SENTINEL_PID}";
}

stop() {
PID=`cat $SENTINEL_PID`
ARGV_HOST=""
BINDIP=`cat $CONF | grep "bind "|awk '{print $2}'`
[ -z $BINDIP ] || ARGV_HOST=" -h "$BINDIP
echo "Stopping $NAME ($PID) ..."
/opt/redis/bin/redis-cli -p 26000 $ARGV_HOST SHUTDOWN
#kill $PID
}

restart() {
echo "Restarting $NAME ..."
stop
start
}

case "$CMD" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
*)
echo "Usage $0 {start|stop|restart}"
esac
在三台主机上都启动sentinel,然后手动终止一个redis进程,查看sentinel的日志输出信息,已经当master终止后,redis的主从切换。

七、基于sentinel内置功能对redis进行监控报警机制的实现
在sentinel的配置文件中有这么两条:

sentinel notification-script mymaster /opt/redis/notify.sh
当master,slaves,sentinel出现异常时会调用这个脚本,同时还会给这个脚本传递两个参数

sentinel client-reconfig-script mymaster /opt/redis/reconfig.sh
当redis主从切换的时候会调用这个脚本,调用的同时会传递给脚本7个参数,分别为:
<master-name> <role> <state> <from-ip> <from-port> <to-ip> <to-port>
cat /opt/redis/bin/notify.sh
#!/bin/sh
#
ACTION=$1
STATUS=$2
LOG=/var/log/omp/redis_notify.log
send_fetion () {
/opt/php/bin/php /opt/omp/sms/send.php "$1" "$2"
}
send_warning(){
STR=$1
mobile_num="159xxxxxxxx,136xxxxxxxx"
hn=`hostname`
STR="$STR `date "+%m-%d %H:%M"` from $hn $ACTION $STATUS"
send_fetion $mobile_num "$STR"
echo "$STR" >> $LOG
}
RESAULT=`echo "$ACTION $STATUS"`
if echo $RESAULT | grep "^[+-]sdown" -sq ;then
send_warning "redis warn"
else
exit 0
fi
cat /opt/redis/bin/reconfig.sh
#!/bin/sh
#
RESAULT=`echo "$1 $2 $3 $4:$5 to $6:$7"`
LOG=/var/log/53kf/omp/redis_reconfig.log
send_fetion () {
/opt/php/bin/php /opt/omp/sms/send.php "$1" "$2"
}
send_warning(){
STR=$1
#        mobile_num="15968108273,13655813908"
mobile_num="15968108273"
hn=`hostname`
STR="$STR `date "+%m-%d %H:%M"` from $hn $RESAULT"
send_fetion $mobile_num "$STR"
echo "$STR" >> $LOG
}
send_warning "redis_master switch"


/opt/omp/sms这个文件夹是一个飞信发送的php的包,可根据具体情况自己配置一下

八、使用zabbix监控redis
1、redis的web页面:

Configuration → Templates → Import




导入redis.xml模板 (redis.xml文件见附件)
这里我用到的redis端口号为6000 如果端口号不同的话,可以:sed -i 's/6000/$your_port/g' redis.xml
2、 在Templates 中选择的列点选Templates Redis_6000

添加进去需要监控的主机 (因为牵扯到公司内部的主机,所以这一步就不截图给大家了)3、 保存4、在相对应的被监控主机中的zabbix_agentd的配置文件zabbix_agentd.conf的末尾添加一行:
UserParameter=redis_stats[*],redis-cli -h 127.0.0.1 -p $1 -a "redis123456" info|grep $2|cut -d : -f2
重启zabbix_agentd即可
九、通过定时任务执行相应脚本监测redis的健康状态 (外部主机检测:)监测脚本对redis的健康状态的监控主要有几个方面:√ 内存的使用率;√ Fork性能;√ 持久化;√ Slave的在线数;√ Sentinel的在线个数
#!/bin/sh
#
CLIEXEC=/opt/redis/bin/redis-cli
HOST_S1=192.168.111.12
HOST_S2=192.168.111.19
HOST_S3=192.168.111.21
DATE=`date "+%m-%d %H:%M"`
_name="master_status"
#examples="master_status xxxx xxxxx..."
REDIS_PORT=6000
REDIS_PASS="redis123456"
SENTINEL_PORT=26000
REDIS_CMD="$CLIEXEC -p $REDIS_PORT -a $REDIS_PASS"
SENTINEL_CMD="$CLIEXEC -p $SENTINEL_PORT"
LOG_DIR="/var/log/omp"
LOG="$LOG_DIR/check_redis.log"
SET_MEM="80.00"
SET_MEM_PEAK="85.00"

[[ -d $LOG_DIR ]] || mkdir $LOG_DIR -p

#####飞信报警功能#####
send_fetion () {
/opt/php/bin/php /opt/omp/sms/send.php "$1" "$2"
}
send_warning(){
STATUS=$1
mobile_num="159xxxxxxxx,136xxxxxxx"
hn=`hostname`
STR="send from $hn $DATE $STATUS"
send_fetion $mobile_num "$STR"
echo "$STR" >> $LOG
}

#####状态检测#####
check_redis (){
MASTER_NAME=$1
for ip in {$HOST_S1,$HOST_S2,$HOST_S3}
do
$SENTINEL_CMD -h $ip PING > /dev/null || continue
MASTER_HOST=`$SENTINEL_CMD -h $ip SENTINEL get-master-addr-by-name $MASTER_NAME | head -n1`
[[ -n $MASTER_HOST ]] && break
done
check_ping_slave $MASTER_HOST
}

check_ping_slave () {
_MASTER=$1
HOSTS=`$SENTINEL_CMD -h $_MASTER sentinel slaves $MASTER_NAME|egrep -o "([0-9]{1,3}\.){3}[0-9]{1,3}"| sort | uniq`
for host in $HOSTS
do
$REDIS_CMD -h $host PING > /dev/null || send_warning "redis_ping_lost to $host"
$SENTINEL_CMD -h $host PING > /dev/null || send_warning "sentinel_ping_lost to $host"
if [[ $host == $_MASTER ]];then
USED_MEM=`$REDIS_CMD -h $host INFO memory |grep used_memory:|tr -d "\r" | awk -F: '{print $2}'`
USED_MEM_PEAK=`$REDIS_CMD -h $host INFO memory |grep used_memory_peak:|tr -d "\r" | awk -F: '{print $2}'`
MAX_MEM=`$REDIS_CMD -h $host config get maxmemory | tail -n1`
USED=`echo "scale=2;$USED_MEM/$MAX_MEM*100" |bc`
USED_PEAK=`echo "scale=2;$USED_MEM_PEAK/$MAX_MEM*100" |bc`
[[ $USED > $SET_MEM ]] && send_warning "redis_memory_warn: $USED_MEM"
[[ $USED_PEAK > $SET_MEM_PEAK ]] && send_warning "redis_memory_peak_warn $USED_PEAK"
else
LINK_STR=`$REDIS_CMD -h $host INFO replication | grep master_link_status | awk -F: '{print $2}'`
[[ $LINK_STR == up ]] || send_warning "master_link_status warn: $host cannot connect to $_MASTER"
fi
done
SLAVE_NUM=`$REDIS_CMD -h $_MASTER INFO replication | grep ^slave |wc -l`
[[ $SLAVE_NUM -lt 2 ]] && send_warning "redis_slave_number warn"
}

#for _name in $examples    #sentinel监控多个master_name时,删除$_name的复制语句
#do                        #启用example的变量复制
check_redis $_name #启用此处的for循环
#done
解释一下上面的几条语句中出现了 tr -d "\r" 由于redis的INFO的输出信息中自作主张的添加了一些非法字符^M大家可以试下执行下面的两条命令对比一下redis-cli -p $PORT INFO redis-cli -p $PORT INFO |cat -et -大家也可以在上述脚本中尝试去掉 tr -d "\r" ,看下输出信息:(standard_in) 1: illegal character: ^M
本文出自 “红楼遗梦” 博客,请务必保留此出处http://leidongya.blog.51cto.com/7375845/1568992
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: