为了账号安全,请及时绑定邮箱和手机立即绑定

《Redis系列专题》 之 利用代理中间件实现大规模Redis集群

作者: 常明,Java架构师
[请尊重原创,盗版必究,转载请指明出处]

fm


前面在《大规模互联网应用Redis架构要点》和《Redis官方集群方案 Redis Cluster》两篇文章中分别介绍了多Redis服务器集群的两种方式,它们是基于客户端sharding的Redis Sharding和基于服务端sharding的Redis Cluster。

客户端sharding技术其优势在于服务端的Redis实例彼此独立,相互无关联,每个Redis实例像单服务器一样运行,非常容易线性扩展,系统的灵活性很强。其不足之处在于:

  1. 由于sharding处理放到客户端,规模进步扩大时给运维带来挑战。

  2. 服务端Redis实例群拓扑结构有变化时,每个客户端都需要更新调整。

  3. 连接不能共享,当应用规模增大时,资源浪费制约优化。

服务端sharding的Redis Cluster其优势在于服务端Redis集群拓扑结构变化时,客户端不需要感知,客户端像使用单Redis服务器一样使用Redis集群,运维管理也比较方便。

不过Redis Cluster正式版推出时间不长,系统稳定性、性能等都需要时间检验,尤其在大规模使用场合。

能不能结合二者优势?即能使服务端各实例彼此独立,支持线性可伸缩,同时sharding又能集中处理,方便统一管理?本篇介绍的Redis代理中间件twemproxy就是这样一种利用中间件做sharding的技术。

twemproxy处于客户端和服务器的中间,将客户端发来的请求,进行一定的处理后(如sharding),再转发给后端真正的Redis服务器。也就是说,客户端不直接访问Redis服务器,而是通过twemproxy代理中间件间接访问。

参照《大规模互联网应用Redis架构要点》中Redis Sharding架构,增加代理中间件的Redis集群架构如下:
q1
twemproxy中间件的内部处理是无状态的,它本身可以很轻松地集群,这样可避免单点压力或故障。

twemproxy又叫nutcracker,起源于twitter系统中redis/memcached集群开发实践,运行效果良好,后代码奉献给开源社区。其轻量高效,采用C语言开发,工程网址是:https://github.com/twitter/twemproxy

twemproxy后端不仅支持redis,同时也支持memcached,这是twitter系统具体环境造成的。

由于使用了中间件,twemproxy可以通过共享与后端系统的连接,降低客户端直接连接后端服务器的连接数量。同时,它也提供sharding功能,支持后端服务器集群水平扩展。统一运维管理也带来了方便。

当然,也是由于使用了中间件代理,相比客户端直连服务器方式,性能上会有所损耗,实测结果大约降低了20%左右。

下面我们就在CentOS6上实际安装并体验下twemproxy:

  1. 下载最新源码版本
wget https://github.com/twitter/twemproxy/archive/v0.4.1.tar.gz
  1. tar xvfz v0.4.1.tar.gz 解压

3.安装autoreconf工具

wget http://ftp.gnu.org/gnu/autoconf/autoconf-latest.tar.gz
tar xvfz autoconf-latest.tar.gz
./configure --prefix=/usr/local
make
make install
  1. 安装automake工具
wget http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz
./configure --prefix=/usr/local
make && make install
  1. 安装libtool工具
wget http://mirrors.kernel.org/gnu/libtool/libtool-2.4.tar.gz
./configure --prefix=/usr/local

如果进行调试测试,添加如下参数,打开调试信息日志

./configure --prefix=/usr/local  --enable-debug=full
make && make install
  1. 编译安装twemproxy
    进入twemproxy-0.4.1主目录
autoreconf -fvi
./configure --prefix=/usr/local
make && make install

nutcracker --h 显示如下信息,安装成功。
q2
7.建立配置文件

twemproxy提供了配置文件模板, 拷贝conf/nutcracker.yml到 /etc 目录下。编辑/etc/nutcracker.yml 内容如下:

test_for_redis:  # redis服务器池名称,可以定义多个服务器池
  listen: 192.168.1.115:22121
  client_connections: 2000  # 客户端最大连接数
  hash: murmur    # hash函数,常用的都支持,提供了十多种
  distribution: ketama #分配模式,提供三种,ketama 一致性hash,modula 求模取余 random 随机
  redis: true  # redis还是memcached 协议
  server_connections: 10  # 连接后端每个redis服务器的最大连接数 
  auto_eject_hosts: true   #根据server_retry_timeout判断连接超时失败达到server_failure_limit规定次数,即将该host从集群中去除
  server_retry_timeout: 10000
  server_failure_limit: 2
  servers:
   - 192.168.1.115:6379:1 redis_1 # IP:端口号:权重 名称
   - 192.168.1.115:6579:1 redis_2

这里auto_eject_hosts语句要重点说明下,当其设置为true时,和后面server_retry_timeout、server_failure_limit一起可以自动识别后端redis节点故障并自动从集群中清除,故障节点排除,将自动加入到集群中,尽量保持Redis的可用性,这很适合将redis作为缓存的场景。

  1. 启动nutcracker
nutcracker -d -c /etc/nutcracker.yml -o /var/log/nutcracker.log -s 22222 -a 192.168.1.115 -i 60000

-d 后台运行
-c 指定配置文件
-o 指定输出日志文件
-s 指定统计监控端口号
-a 指定统计监控IP
-i 统计更新间隔,单位毫秒
  1. 程序客户端测试

Jedis驱动,编写测试用例,配置文件如下:

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">  
  <property name="maxTotal"  value="4096"/>  
  <property name="maxIdle" value="200"/>  
  <property name="maxWaitMillis" value="3000"/>
  <property name="testOnBorrow" value="true" />
  <property name="testOnReturn" value="true" />
</bean>  

<bean id="jedisPool" class="redis.clients.jedis.JedisPool">  
  <constructor-arg index="0" ref="poolConfig"/>  
  <constructor-arg index="1" value="192.168.1.115" type="String"/>  
  <constructor-arg index="2" value="22121" type="int"/>
  <constructor-arg index="3" value="2000" type="int"/> 
</bean> 

Java测试用例代码如下:

@Test
public void basicOpTestForTwemproxy(){

  long begin = System.currentTimeMillis();   

  Jedis jedis = jedisPool.getResource();

  for(int i=0;i<10000; i++){

    jedis.set("person." + i + ".name", "frank");
    jedis.set("person." + i + ".city", "beijing");

    String name = jedis.get("person." + i + ".name");
    String city = jedis.get("person." + i + ".city");

    assertEquals("frank",name);
    assertEquals("beijing",city);

    jedis.del("person." + i + ".name");
    Boolean result = jedis.exists("person." + i + ".name");
    assertEquals(false,result);

    result = jedis.exists("person." + i + ".city");
    assertEquals(true,result);

  }

  jedis.close();

  long end = System.currentTimeMillis();   

  System.out.println("total time: " + (end-begin)/1000);

}
  1. 监控统计数据

twemproxy提供了基本的统计数据接口,数据采用json格式,可以使用telnet命令查看:
图片描述
利用这些基本数据,可以开发更友好的图形化监控工具。
图片描述

点击查看更多内容
9人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
455
获赞与收藏
3117

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消