一、前言
1.Why 集群?
当前各家互联网公司为了提高站点响应速度,使用缓存工具将热点数据保存在内存中,避免直接从后端数据库读取查询,降低后端压力。其中常见的cache工具有memcache和redis,相较于memcache,redis有着许多优势,这里不再赘述。
在大型站点应用中,热点数据几十上百G也很普遍,而无论是物理机、云主机(虚拟机),内存资源往往是有限的,虽然目前硬件成本降低,几十G几十核的主机也很常见,但是对于redis这种工作进程为单线程模式的工具来说,一台主机只运行一个实例就有些浪费,且出现单点故障时影响范围很大。同时,redis管理大内存时不如管理相对较小的内存高效,据第三方测试,redis单进程内存分配达到20G后性能急剧下降,因此普遍使用的方式为单进程分配8G内存,单主机开启多个redis instance.
2.How 集群?
⑴.Redis官方集群方案 Redis Cluster(服务端sharding)
Redis cluster是一种在服务端sharding(分片)的技术,在redis3.0版本开始正式提供。
Redis cluster的服务端sharding引入了slot(槽)的概念,一共分为16384(2^14)个slot,集群中的每个node节点负责分摊这些slot,每个进入redis的键值对,根据key进行hash运算,除以16384取模,匹配相应的slot,再分配进相应的node中的实例中。在redis cluster方案中,数据储存的粒度由原来的instance再次精细为slot。
Redis cluster提供一种叫做cluster bus(集群总线)的功能特性,采用特殊的二进制协议,通信及响应速度极快。它提供节点故障检测、故障转移、新节点识别等节点管理功能,该功能的进程间通信端口号为服务端口号值+10000,例如redis对外提供服务的端口号为6555,则cluster bus的端口号则为16555。
值得注意的是:redis cluster是官方在3.0以后的版本才正式推出的,虽然目前社区内比较活跃,但是成熟的生产案例还不多,需要时间考验。
⑵.redis sharding 集群(客户端sharding)
Redis 3.0服务端sharding推出之前,采用的较普遍的client端集群方式,工作逻辑为:将键值对中的key使用hash算法散列,特定的key映射至特定的redis 实例上,然后由client端主动向该node set/get数据,server端则工作在被动模式。
目前java redis的客户端驱动jedis已经支持redis sharding的功能。
但是Redis sharding面临的问题:扩容。在client端sharding模式下,数据控制完全由client端掌控,redis集群各node间彼此独立,因此在扩容(或缩容)时,数据无法直接从原node转向新node,这时会造成缓存无法命中的问题,查询/写入请求会透过缓存层直接访问后端DB,给后端带来较大的压力,为了避免这个问题,官方给出了比较讨巧的解决方案:presharding。
⑶.代理中间件sharding
上面分别介绍了多Redis服务器集群的两种方式,它们是基于客户端sharding的Redis Sharding和基于服务端sharding的Redis Cluster。
客户端sharding技术
其优势在于服务端的Redis实例彼此独立,相互无关联,每个Redis实例像单服务器一样运行,非常容易线性扩展,系统的灵活性很强。
其不足之处在于:
由于sharding处理放到客户端,规模进步扩大时给运维带来挑战。
服务端Redis实例群拓扑结构有变化时,每个客户端都需要更新调整。
连接不能共享,当应用规模增大时,资源浪费制约优化。
服务端sharding的Redis Cluster
其优势在于服务端Redis集群拓扑结构变化时,客户端不需要感知,客户端像使用单Redis服务器一样使用Redis集群,运维管理也比较方便。
不过Redis Cluster正式版推出时间不长,系统稳定性、性能等都需要时间检验,尤其在大规模使用场合。
能不能结合二者优势?即能使服务端各实例彼此独立,支持线性可伸缩,同时sharding又能集中处理,方便统一管理?本篇主要介绍的Redis代理中间件twemproxy就是这样一种利用中间件做sharding的技术。
twemproxy处于客户端和服务器的中间,将客户端发来的请求,进行一定的处理后(如sharding),再转发给后端真正的Redis服务器。也就是说,客户端不直接访问Redis服务器,而是通过twemproxy代理中间件间接访问。twemproxy中间件的内部处理是无状态的,它本身可以很轻松地做LB/HA集群,这样可避免单点压力或故障。twemproxy又叫nutcracker,起源于twitter系统中redis/memcached集群开发实践,运行效果良好,后代码奉献给开源社区。其轻量高效,采用C语言开发。
GitHub link:
(https://github.com/twitter/twemproxy)
twemproxy后端不仅支持redis,同时也支持memcached,这是twitter系统具体环境造成的。由于使用了中间件,twemproxy可以通过共享与后端系统的连接,降低客户端直接连接后端服务器的连接数量。同时,它也提供sharding功能,支持后端服务器集群水平扩展。统一运维管理也带来了方便。当然,也是由于使用了中间件代理,相比客户端直连服务器方式,性能上会有所损耗,Twitter官方实测结果大约降低了20%左右,不过性能的部分损耗可以依靠增加集群节点数量来弥补。
So,开始实验吧~
二、环境
虚拟机:
redis server:192.168.0.168:6666 6667 6668 #三个实例 4G ram
twemproxy-server1:192.168.0.68
twemproxy-server2:192.168.0.69 #vip:192.168.0.66
Centos 6.8,关闭iptables、selinux
三、准备工具包
1.安装配置redis
提前安装gcc,配置好epel源可以yum 直接安装
[root@redis redis]# cd /usr/local/packages/
[root@redis redis]# tar -xf redis-3.2.10.tar.gz
[root@redis redis]# cd redis-3.2.10
[root@redis redis]# make && make install
[root@redis redis]#mkdir /etc/redis
[root@redis redis]#mkdir -pv /usr/local/redis/bin
[root@redis redis]#cp redis.conf /etc/redis/
[root@redis redis]#cp src/{redis-cli,redis-server,redis-benchmark} /usr/local/redis/bin
[root@redis redis]#cd /etc/redis/
[root@redis redis]#cp redis.conf redis.conf.bak
[root@redis redis]#mv redis.conf redis_6666.conf
##vim redis_6666.conf,修改工作端口号,pid路径,maxmemory=1G,注意,bind ip一定要修改为当前网卡IP,不能使用127.0.0.1 ##
[root@redis redis]#cp redis_6666.conf redis_6667.conf
[root@redis redis]#cp redis_6666.conf redis_6668.conf
[root@redis redis]# /usr/local/redis/bin/redis-server /etc/redis/redis_6666.conf
[root@redis redis]# /usr/local/redis/bin/redis-server /etc/redis/redis_6667.conf
[root@redis redis]# /usr/local/redis/bin/redis-server /etc/redis/redis_6668.conf
三个进程全部已启动
[root@redis redis]# ss -anlp | grep redis
LISTEN 0 128 127.0.0.1:6666 *:* users:(("redis-server",13316,4))
LISTEN 0 128 127.0.0.1:6667 *:* users:(("redis-server",13339,4))
LISTEN 0 128 127.0.0.1:6668 *:* users:(("redis-server",13344,4))**
用自带redis-cli登入正常
[root@redis redis]# /usr/local/redis/bin/redis-cli -p 6666
[root@redis redis]# /usr/local/redis/bin/redis-cli -p 6667
[root@redis redis]# /usr/local/redis/bin/redis-cli -p 6668
2.安装配置twemproxy
编译安装autoconf
[root@twemproxy-server ~]# wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
[root@twemproxy-server ~]# tar -zvxf autoconf-2.69.tar.gz
[root@twemproxy-server ~]# cd autoconf-2.69
[root@twemproxy-server autoconf-2.69]# ./configure && make && make install
编译安装automake
[root@twemproxy-server ~]# wget http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz
[root@twemproxy-server ~]# tar -zvxf automake-1.15.tar.gz
[root@twemproxy-server ~]# cd automake-1.15
[root@twemproxy-server automake-1.15]# ./configure && make && make install
编译安装libtool
[root@twemproxy-server ~]# wget https://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz
[root@twemproxy-server ~]# tar -zvxf libtool-2.4.6.tar.gz
[root@twemproxy-server ~]# cd libtool-2.4.6
[root@twemproxy-server libtool-2.4.6]# ./configure && make && make install
编译安装配置twemproxy
[root@twemproxy-server ~]# cd /usr/local/packages
[root@twemproxy-server ~]# tar -xf twemproxy-0.4.1.tar.gz
[root@twemproxy-server ~]# cd cd twemproxy-0.4.1
[root@twemproxy-server-2 twemproxy-0.4.1]# aclocal
[root@twemproxy-server-2 twemproxy-0.4.1]# autoreconf -f -i -Wall,no-obsolete //执行autoreconf 生成 configure文件等
[root@twemproxy-server-2 twemproxy-0.4.1]# ./configure --prefix=/usr/local/twemproxy/
[root@twemproxy-server-2 twemproxy-0.4.1]# make && make install
[root@twemproxy-server-2 twemproxy-0.4.1]cp -r conf/ /usr/local/twemproxy/
[root@twemproxy-server ~]cd /usr/local/twemproxy/conf
[root@twemproxy-server ~]vim nutcracker.yml
alpha: //随意命名
listen: 0.0.0.0:22121 #结合keepalived时必须配置为0.0.0.0
hash: fnv1a_64
distribution: ketama
auto_eject_hosts: true
redis: true
server_retry_timeout: 2000
server_failure_limit: 1
servers:
- 192.168.0.168:6666:1
- 192.168.0.168:6667:1
- 192.168.0.168:6668:1 //分片成3部分,格式ip:port:weight
启动查看twemproxy:
[root@twemproxy-server ~] /usr/local/twemproxy/sbin/nutcracker -c /usr/local/twemproxy/conf/nutcracker.yml &
[root@twemproxy-server ~]ss -tnlp | grep twemproxy
[root@haproxy-b conf]# ss -tnlp
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 192.168.0.69:22121 *:* users:(("nutcracker",2581,5))
LISTEN 0 128 *:22222 *:* users:(("nutcracker",2581,3))
在redis端使用redis-cli登陆twemproxy并设置key-value成功:
3.keepalive配置
twemproxy-server2配置同server1,这里不贴了。
epel源中有keepalived包,直接安装:
yum -y install keepalived
主配置:
[root@haproxy-m conf]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1 #生产环境设置真实mail server
smtp_connect_timeout 10
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state MASTER
interface eth1
virtual_router_id 51
priority 101
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.66
}
track_interface {
eth1
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault" //通知及响应脚本
}
备配置:
[root@haproxy-b twemproxy]# cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
root@localhost
}
notification_email_from keepalived@localhost
smtp_server 127.0.0.1
smtp_connect_timeout 10
router_id LVS_DEVEL
}
vrrp_instance VI_1 {
state BACKUP
interface eth2
virtual_router_id 51
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.0.66
}
track_interface {
eth2
}
notify_master "/etc/keepalived/notify.sh master"
notify_backup "/etc/keepalived/notify.sh backup"
notify_fault "/etc/keepalived/notify.sh fault"
}
notify.sh:
[root@ twemproxy-server]# cat /etc/keepalived/notify.sh
#!/bin/bash
vip=192.168.0.66
reciever='root@localhost'
notify() {
mailsubject="`hostname`turn to $1,$vip switched"
mailbody="`date`,vrrp status changed:`hostname` changed to be $1"
echo "$mailbody" | mail -s "$mailsubject" $reciever
}
case "$1" in
backup)
notify backup
exit 0
;;
master)
notify master
exit 0
;;
fault)
notify fault
service keepalived restart
exit 0
;;
*)
echo "usage:please input $0 with {master|backup|fault}"
exit 1
;;
esac
启动keepalived并查看vip位置,vip在master机上:
将twemproxy主的网卡shutdown,查看备机,VIP已转移至备机:
至此,高可用twemproxy代理redis集群部署完成。
扩展思路:
1.redis节点配置为主从模式,故障检测,主备切换
2.redis主备节点配置为读写分离模式,热点数据通常读写比例为5:1以上,可配置为一主(写)拖N从(读)