前面在《大规模互联网应用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集群架构如下:

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

2. 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

4. 安装automake工具

wget http://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz

./configure --prefix=/usr/local

make && make install

5. 安装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

 

6. 编译安装twemproxy

进入twemproxy-0.4.1主目录

 

autoreconf -fvi

./configure --prefix=/usr/local

make && make install

nutcracker --h 显示如下信息,安装成功。

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作为缓存的场景。

8. 启动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 统计更新间隔,单位毫秒

9. 程序客户端测试

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);

}

10. 监控统计数据

twemproxy提供了基本的统计数据接口,数据采用json格式,可以使用telnet命令查看:

利用这些基本数据,可以开发更友好的图形化监控工具。

161230、利用代理中间件实现大规模Redis集群的更多相关文章

  1. Redis集群方案应该怎么做

    方案1:Redis官方集群方案 Redis Cluster Redis Cluster是一种服务器sharding分片技术.Redis Cluster集群如何搭建请参考我的另一篇博文:http://w ...

  2. Redis集群方案<转>

    为什么集群? 通常,为了提高网站响应速度,总是把热点数据保存在内存中而不是直接从后端数据库中读取.Redis是一个很好的Cache工具.大型网站应用,热点数据量往往巨大,几十G上百G是很正常的事儿,在 ...

  3. redis集群与分片(1)-redis服务器集群、客户端分片

    下面是来自知乎大神的一段说明,个人觉得非常清晰,就收藏了. 为什么集群? 通常,为了提高网站响应速度,总是把热点数据保存在内存中而不是直接从后端数据库中读取.Redis是一个很好的Cache工具.大型 ...

  4. Redis集群方案(来自网络)

    参考: https://www.zhihu.com/question/21419897 http://www.cnblogs.com/haoxinyue/p/redis.html 为什么集群? 通常, ...

  5. Bash实践:抽样检测数据迁移至Redis集群后的数据一致性

    熟悉了一段时间的Bash编程,因此借此任务操作一把bash编程,主要涉及到Redis单节点与Redis集群的操作 1. 任务背景 近日有个任务需要将历史的Redis(主从节点)中的数据迁移至Redis ...

  6. laravel项目利用twemproxy部署redis集群的完整步骤

    Twemproxy是一个代理服务器,可以通过它减少Memcached或Redis服务器所打开的连接数.下面这篇文章主要给大家介绍了关于laravel项目利用twemproxy部署redis集群的相关资 ...

  7. 基于vip和twemproxy代理实现redis集群的无感知弹性扩容

    目标是实现redis集群的无感知弹性扩容 关键点 1是无感知,即对redis集群的用户来说服务ip和port保持不变 2.弹性扩容,指的是在需要时刻可以按照业务扩大redis存储容量. 最原始的twe ...

  8. 为什么Redis集群要使用反向代理?

    为什么要使用反向代理? 如果没有方向代理,一台Redis可能需要跟很多个客户端连接: 看着是不是很慌?看没关系,主要是连接需要消耗线程资源,没有代理的话,Redis要将很大一部分的资源用在与客户端建立 ...

  9. 利用docker部署redis集群

    目录 一.首先配置redis.conf文件,... 1 1.获取配置文件... 1 2.修改各配置文件的参数... 2 二.下载redis镜像.启动容器... 2 1.创建网络... 2 2.拉取镜像 ...

随机推荐

  1. Cocos引擎开发者指南(1-5)

    Cocos引擎开发者指南 英文原版:http://www.cocos2d-x.org/docs/programmers-guide/1/ 中午翻译:http://www.cocos.com/doc/t ...

  2. rabbitmq使用心得

    因为公司项目需要使用消息中间件,实现相关业务的异步处理,所有选用了rabbitmq.通过看文档,爬过一个一个坑,终于还是实现了相关功能. 直接上配置文件: <?xml version=" ...

  3. track message forwards, avoiding request loops, and identifying the protocol capabilities of all senders along the request/response chain

    https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html The TRACE method is used to invoke a remote, ...

  4. Nodejs:Path对象

    模块Path: path.normalize(url) path.join(url1, url2, ..) path.resolve(url1, url2, ..) path.relative(url ...

  5. CocoaPods for Xcode

    http://www.cnblogs.com/MrRed/p/5728933.html 非常方便的Xcode pods插件.可以很方便的在Xcode通过pods安装各种objective-c第三方库, ...

  6. (转)微信小程序破解IDE

    1.IDE下载 微信web开发者工具,本人是用的windows 10 x64系统,用到以下两个版本的IDE安装工具与一个破解工具包: wechat_web_devtools_0.7.0_x64.exe ...

  7. Angular-ngtable联动全选

    之前于Angular第三方插件ngTable的官网demo上看到的例子,但苦于demo中联动全选为选中所有,项目中并不适用,因此做了下小小的修改,修改目的只是为实现其功能,方法不敢苟同,若有更加简便的 ...

  8. JMeter学习-027-JMeter参数文件(脚本分发)路径问题:jmeter.threads.JMeterThread: Test failed! java.lang.IllegalArgumentException: File distributed.csv must exist and be readable解决方法

    前些天,在进行分布式参数化测试的时候,出现了如题所示的错误报错信息.此文,针对此做一个简略的重现及分析说明. JMX脚本线程组参数配置如下所示: 参数文件路径配置如下所示: 执行JMX脚本后,服务器对 ...

  9. php代码性能分析方法

    1.用到的函数 microtime() ,函数返回当前 Unix 时间戳和微秒数,本函数以 "msec sec" 的格式返回一个字符串,其中 sec 是自 Unix 纪元(0:00 ...

  10. Java 使用GDAL 读写 shapefile

    读取shp文件,并把它转化为json import org.gdal.ogr.*; import org.gdal.ogr.Driver; import org.gdal.gdal.*; public ...