Redis集群:基于twemproxy的实现

Redis集群:基于twemproxy的实现

一、前言

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集群:基于twemproxy的实现_第1张图片

虚拟机:
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成功:
Redis集群:基于twemproxy的实现_第2张图片

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机上:
Redis集群:基于twemproxy的实现_第3张图片

4.操作测试
通过vip访问,set/get数据成功:
Redis集群:基于twemproxy的实现_第4张图片

将twemproxy主的网卡shutdown,查看备机,VIP已转移至备机:
Redis集群:基于twemproxy的实现_第5张图片

客户端访问redis数据正常:
Redis集群:基于twemproxy的实现_第6张图片

至此,高可用twemproxy代理redis集群部署完成。

扩展思路:
1.redis节点配置为主从模式,故障检测,主备切换
2.redis主备节点配置为读写分离模式,热点数据通常读写比例为5:1以上,可配置为一主(写)拖N从(读)

参考文档:
Redis集群:基于twemproxy的实现_第7张图片

你可能感兴趣的:(Linux)