redis系列twemproxy

1  简单介绍

twemproxy,也叫nutcraker。是一个twitter开源的一个redis memcache 快速/轻量级代理服务器。如果使用过nginx的反向代理或者mysql的代理工具,如amoeba,你也能很快理解这个redis proxy。twemproxy是一个快速的单线程代理程序,支持memcached ASCII协议和更新的Redis协议。

twemproxy通过引入一个代理层,可以将其后端的多台redismemcached 实例进行统一管理与分配,使应用程序只需要在twemproxy上进行操作,而不用关心后面具体有多少个真实的redismemcached存储。

         通过twemproxy可以使用多台服务器来水平扩张redis服务,可以有效的避免单点故障问题。虽然使用twemproxy需要更多的硬件资源和在redis性能有一定的损失(twitter测试约20%),但是能够提高整个系统的HA也是相当划算的。

本文将介绍如果使用twemproxy实现redis数据分片搭建一套强大的redis集群。

2  twemproxy编译和安装

2.1  依赖编译和安装

2.1.1  编译安装autoconf

## 下载 && 解压并安装

$ wgethttp://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz

$ tar zxfautoconf-2.69.tar.gz

$ ./configure

$ make&& make install

2.1.2  编译安装automake

## 下载 && 解压并安装

$ wgethttp://ftp.gnu.org/gnu/automake/automake-1.15.tar.gz

$ tar zxfautomake-1.15.tar.gz

$ ./configure

$ make &&make install

2.1.3  编译安装libtool

## 下载 && 解压并安装

$ wgethttps://ftp.gnu.org/gnu/libtool/libtool-2.4.6.tar.gz

$ tar zxflibtool-2.4.6.tar.gz

$ cdlibtool-2.4.6

$ ./configure

$ make&& make install

2.2  twemproxy编译

         twemproxy的项目的源码在GitHub上面,下载下来就可以编译。

         $git clone https://github.com/twitter/twemproxy.git

$ cd twemproxy

$ autoreconf-fvi

$ ./configure--enable-debug=full

$ make

$ src/nutcracker-h

3  nutcracker用法与命令

Options:

-h,  -help             : 查看帮助文档,显示命令选项

-V,  -version           : 查看nutcracker版本

-t,  -test-conf          : 测试配置脚本的正确性

-d,  -daemonize        : 以守护进程运行

-D,  -describe-stats      : 打印状态描述

-v,  -verbosity=N        : 设置日志级别 (default: 5, min: 0, max: 11)

-o,  -output=S          : 设置日志输出路径,默认为标准错误输出 (default: stderr)

-c,  -conf-file=S         : 指定配置文件路径 (default: conf/nutcracker.yml)

-s,  -stats-port=N       : 设置状态监控端口,默认22222(default: 22222)

-a,  -stats-addr=S       : 设置状态监控IP,默认0.0.0.0(default: 0.0.0.0)

-i,  -stats-interval=N     : 设置状态聚合间隔 (default:30000 msec)

-p,  -pid-file=S          : 指定进程pid文件路径,默认关闭 (default: off)

-m,  -mbuf-size=N       : 设置mbuf块大小,以bytes单位 (default:16384 bytes)

4  twemproxy的配置

twemproxy的配置信息填写在nutcracker.yml之中,默认的查找位置是在conf目录下,也可以通过-c参数指定。

例如:

$ cat nutcracker.yml

Redis_test:

listen: 127.0.0.1:22222

hash: fnv1a_64

distribution: ketama

auto_eject_hosts: true

redis: true

server_retry_timeout: 30000

server_failure_limit: 1

servers:

- 10.1.51.248:6379:1 master01

- 10.1.51.199:6379:1 master02

4.1  listen

         twemproxy监听的端口。

       例如:listen: 10.1.51.248:22210

4.2  hash

默认是fnv1a_64,可以选择的key值的hash算法:

1one_at_a_time

2md5

3crc16

4crc32(crc32implementation compatible with libmemcached)

5crc32a(correctcrc32 implementation as per the spec)

6fnv1_64

7fnv1a_64

8fnv1_32

9fnv1a_32

10hsieh

11murmur

12jenkins


4.3  hash_tag

hash_tag允许根据key的一个部分来计算keyhash值。hash_tag由两个字符组成,一个是hash_tag的开始,另外一个是hash_tag的结束,在hash_tag的开始和结束之间,是将用于计算keyhash值的部分,计算的结果会用于选择服务器。


例如:hash_tag: {}

如果key {commondata}:ids_uer_aaakey{commondata}:ids_uer_bbbhash值都是基于commondata,会被映射到同一台服务器。

如果keycommondata:ids_uer_aaahash值将使用整个key来计算,可能会被映射到不同的服务器。



4.4  distribution

存在ketamamodularandom3种可选的配置。其含义如下:

1ketama

ketama一致性hash算法,会根据服务器构造出一个hash ring,并为ring上的节点分配hash范围。ketama的优势在于单个节点添加、删除之后,会最大程度上保持整个群集中缓存的key值可以被重用。

2modula

modula非常简单,就是根据key值的hash值取模,根据取模的结果选择对应的服务器。

3random

random是无论key值的hash是什么,都随机的选择一个服务器作为key值操作的目标。


4.5  timeout

单位是毫秒,是连接到server的超时值。默认是永久等待。


4.6  backlog

监听TCPbacklog(连接等待队列)的长度,默认是512

4.7  preconnect

是一个boolean值,指示twemproxy是否应该预连接pool中的server。默认是false

4.8  redis

是一个boolean值,用来识别到服务器的通讯协议是redis还是memcached。默认是false

4.9  server_connections

每个server可以被打开的连接数。默认,每个服务器开一个连接。

4.10  auto_eject_hosts

是一个boolean值,默认是false,用于控制Twemproxy是否应该根据server的连接状态重建群集。这个连接状态是由server_failure_limit 阀值来控制。

4.11  server_retry_timeout

单位是毫秒,控制服务器连接的时间间隔,在auto_eject_host被设置为true的时候产生作用。默认是30000 毫秒。

4.12  server_failure_limit

控制连接服务器的次数,在auto_eject_host被设置为true的时候产生作用。默认是2

4.13  servers

一个pool中的服务器的地址、端口和权重的列表,包括一个可选的服务器的名字,如果提供服务器的名字,将会使用它决定server的次序,从而提供对应的一致性hashhash ring。否则,将使用server被定义的次序。


例如:

servers:

- 10.1.51.248:6379:1 master01

- 10.1.51.199:6379:1master02

注意:

1 表示权重

master01master02表示服务器名称


5  twemproxy的特性

5.1  支持失败节点自动删除

1、可以设置重新连接该节点的时间

2、可以设置连接多少次之后删除该节点

5.2  支持设置HashTag

1、通过HashTag可以自己设定将两个key哈希到同一个实例上去

2、减少与redis的直接连接数

3、保持与redis的长连接

4、减少了客户端直接与服务器连接的连接数量

5.3  自动分片到后端多个redis实例上

1、多种hash算法:md5crc16crc32 crc32afnv1_64fnv1a_64fnv1_32fnv1a_32hsiehmurmurjenkins

2、多种分片算法:ketama(一致性hash算法的一种实现)modularandom

3、可以设置后端实例的权重

5.4  避免单点问题

可以平行部署多个代理层,通过HAProxy做负载均衡,将redis的读写分散到多个twemproxy上。

5.5  支持状态监控

1、可设置状态监控ip和端口,访问ip和端口可以得到一个json格式的状态信息串

2、可设置监控信息刷新间隔时间

5.6  使用 pipelining 处理请求和响应

1、连接复用,内存复用

2、将多个连接请求,组成reidspipelining统一向redis请求

5.7  并不是支持所有redis命令

1、不支持redis的事务操作

2、使用SIDFF,SDIFFSTORE, SINTER, SINTERSTORE, SMOVE, SUNION and SUNIONSTORE命令需要保证key都在同一个分片上。

6  twemproxy注意点和建议


6.1  一致性hash的选择

         twemproxy的群集的一致性hash算法的配置,有3个选择:ketamamodularandom

random是随机的选择一个redisserver作为最终操作的目标,这个适合只读的场景,需要配合数据加载。

ketama是一种基于key-range的一致性hash算法,它的优势是一个redisserverdown掉之后,整个群集做re-hash,会有一部分key-range与以前的key-range重合。这种特性也是只适合做比较单纯cache

modula的方式是根据keyhash取模,来选择目标的redisserver。这种方式,显而易见,如果一个redis server down掉之后,如果整个群集做re-hash,所有的key值的目标都会错乱。而是否做整个群集的re-hash,这由TwemproxyLiveness配置来决定。

Liveness配置的开启由auto_eject_hosts来检测,轮询的周期由server_retry_timeout来决定,而server_failure_limit则决定如果几次轮询失败,会将该redis server从群集中摘除。

TwemproxyLiveness需要根据情况谨慎配置。

6.2  HashTags

1hash tag的具体解释可以看我们对Twemproxy的配置方面的描述,简单的说,hash tag可以根据key的一部分作为选择redis server的键值,从而来干预内容存在何处。

2hash tag很简单,就2个字符,前面是引导字符,后面是结束字符,在这两个字符中间的被作为最终用于作为群集一致性hashkey值。

注意:

如果在key中没找到对应的hash_tags模式,会使用整个key作为一致性hashkey值。

6.3  key值长度的限制

memcache限制key值在250字符以内,redis则没什么限制,由于Twemproxykey值存放在连续的内存之中,所以Twemproxykey值的最大长度受到mbuf长度的限制。

mbuf的长度由-m指定,默认是16384字节,一般够用了。如果遇到key值过长的问题,可以调整这个参数。

6.4  mbuf

mbuf最小512字节,最大65536字节,默认16384字节。可以通过命令行的-m参数调整。

mbufTwemproxy引以为傲的zero-copy技术的底层支撑,zero-copy意味着从客户端接收的数据直接被提交到redis-server,不需要经过中间的copy环节(看似不难,实际上操作起来很难做到)。

很明显,大尺寸的mbuf会增加性能,减少分包的次数,但是会增加对内存的消耗。

如何估计twemproxymbuf对内存的需求呢?公式如下:

max(client_connections,server_connections) * 2 *mbuf-size

因为存在client-> twemproxy以及twemproxy->redis-server两个连接,所以mbuf是需要双份的。

大多客户端的连接会大于服务器连接池预设的连接数。我们假设1000个客户端连接,mbuf-size16KB,那么大概会消耗掉1000*2*16KB=32M左右的内存。

6.5  twemproxy高可用策略

1、twemproxy动态移除不可用的节点,但是该节点的数据丢失了,这个缺点是最致命的,最好每个节点后面跟一个从节点,使用Keepalived+VIP,可以故障漂移,从节点自动升级为主节点,保证了高可用性。

7  twemproxy缺点

1、支持动态移除节点,但该移除节点的数据就丢失了。

2、动态增加节点的时候,twemproxy不会对已有数据做重分布,这个需要自己写个脚本实现。

3、性能上的损耗,其实作为代理必定会有损耗,twemproxy损耗属于很小的级别了。

4、不支持针对多个值的操作,比如取sets的子交并补等(MGET DEL 除外)。

5、不支持Redis的事务操作。

6、出错提示还不够完善。

 

 

 

 

 

 

 

 

 

 

参考链接:

http://haoran-10.iteye.com/blog/2264084

https://my.oschina.net/dchuang/blog/666827

http://blog.csdn.net/zhaokuner/article/details/23333199

http://mdba.cn/2013/10/23/twemproxy%E5%AE%89%E8%A3%85/

 

09-29 08:42