https://github.com/twitter/twemproxy
redis系列twemproxy
1 简单介绍
twemproxy,也叫nutcraker。是一个twitter开源的一个redis 和memcache 快速/轻量级代理服务器。如果使用过nginx的反向代理或者mysql的代理工具,如amoeba,你也能很快理解这个redis proxy。twemproxy是一个快速的单线程代理程序,支持memcached ASCII协议和更新的Redis协议。
twemproxy通过引入一个代理层,可以将其后端的多台redis或memcached 实例进行统一管理与分配,使应用程序只需要在twemproxy上进行操作,而不用关心后面具体有多少个真实的redis或memcached存储。
通过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算法:
1、one_at_a_time
2、md5
3、crc16
4、crc32(crc32implementation compatible with libmemcached)
5、crc32a(correctcrc32 implementation as per the spec)
6、fnv1_64
7、fnv1a_64
8、fnv1_32
9、fnv1a_32
10、hsieh
11、murmur
12、jenkins
4.3 hash_tag
hash_tag允许根据key的一个部分来计算key的hash值。hash_tag由两个字符组成,一个是hash_tag的开始,另外一个是hash_tag的结束,在hash_tag的开始和结束之间,是将用于计算key的hash值的部分,计算的结果会用于选择服务器。
例如:hash_tag: {}
如果key为 {commondata}:ids_uer_aaa和key为{commondata}:ids_uer_bbb的hash值都是基于commondata,会被映射到同一台服务器。
如果key为commondata:ids_uer_aaa的hash值将使用整个key来计算,可能会被映射到不同的服务器。
4.4 distribution
存在ketama、modula和random3种可选的配置。其含义如下:
1、ketama
ketama一致性hash算法,会根据服务器构造出一个hash ring,并为ring上的节点分配hash范围。ketama的优势在于单个节点添加、删除之后,会最大程度上保持整个群集中缓存的key值可以被重用。
2、modula
modula非常简单,就是根据key值的hash值取模,根据取模的结果选择对应的服务器。
3、random
random是无论key值的hash是什么,都随机的选择一个服务器作为key值操作的目标。
4.5 timeout
单位是毫秒,是连接到server的超时值。默认是永久等待。
4.6 backlog
监听TCP的backlog(连接等待队列)的长度,默认是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的次序,从而提供对应的一致性hash的hash ring。否则,将使用server被定义的次序。
例如:
servers:
10.1.51.248:6379:1 master01
10.1.51.199:6379:1master02
注意:
1 表示权重
master01和master02表示服务器名称
5 twemproxy的特性
5.1 支持失败节点自动删除
1、可以设置重新连接该节点的时间
2、可以设置连接多少次之后删除该节点
5.2 支持设置HashTag
1、通过HashTag可以自己设定将两个key哈希到同一个实例上去
2、减少与redis的直接连接数
3、保持与redis的长连接
4、减少了客户端直接与服务器连接的连接数量
5.3 自动分片到后端多个redis实例上
1、多种hash算法:md5、crc16、crc32 、crc32a、fnv1_64、fnv1a_64、fnv1_32、fnv1a_32、hsieh、murmur、jenkins
2、多种分片算法:ketama(一致性hash算法的一种实现)、modula、random
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个选择:ketama、modula和random。
random是随机的选择一个redisserver作为最终操作的目标,这个适合只读的场景,需要配合数据加载。
ketama是一种基于key-range的一致性hash算法,它的优势是一个redisserverdown掉之后,整个群集做re-hash,会有一部分key-range与以前的key-range重合。这种特性也是只适合做比较单纯cache。
modula的方式是根据key的hash取模,来选择目标的redisserver。这种方式,显而易见,如果一个redis server down掉之后,如果整个群集做re-hash,所有的key值的目标都会错乱。而是否做整个群集的re-hash,这由Twemproxy的Liveness配置来决定。
Liveness配置的开启由auto_eject_hosts来检测,轮询的周期由server_retry_timeout来决定,而server_failure_limit则决定如果几次轮询失败,会将该redis server从群集中摘除。
Twemproxy的Liveness需要根据情况谨慎配置。
6.2 HashTags
1、hash tag的具体解释可以看我们对Twemproxy的配置方面的描述,简单的说,hash tag可以根据key的一部分作为选择redis server的键值,从而来干预内容存在何处。
2、hash tag很简单,就2个字符,前面是引导字符,后面是结束字符,在这两个字符中间的被作为最终用于作为群集一致性hash的key值。
注意:
如果在key中没找到对应的hash_tags模式,会使用整个key作为一致性hash的key值。
6.3 key值长度的限制
memcache限制key值在250字符以内,redis则没什么限制,由于Twemproxy将key值存放在连续的内存之中,所以Twemproxy的key值的最大长度受到mbuf长度的限制。
mbuf的长度由-m指定,默认是16384字节,一般够用了。如果遇到key值过长的问题,可以调整这个参数。
6.4 mbuf
mbuf最小512字节,最大65536字节,默认16384字节。可以通过命令行的-m参数调整。
mbuf是Twemproxy引以为傲的zero-copy技术的底层支撑,zero-copy意味着从客户端接收的数据直接被提交到redis-server,不需要经过中间的copy环节(看似不难,实际上操作起来很难做到)。
很明显,大尺寸的mbuf会增加性能,减少分包的次数,但是会增加对内存的消耗。
如何估计twemproxy的mbuf对内存的需求呢?公式如下:
max(client_connections,server_connections) * 2 *mbuf-size
因为存在client-> twemproxy以及twemproxy->redis-server两个连接,所以mbuf是需要双份的。
大多客户端的连接会大于服务器连接池预设的连接数。我们假设1000个客户端连接,mbuf-size是16KB,那么大概会消耗掉1000216KB=32M左右的内存。
6.5 twemproxy高可用策略
1、twemproxy动态移除不可用的节点,但是该节点的数据丢失了,这个缺点是最致命的,最好每个节点后面跟一个从节点,使用Keepalived+VIP,可以故障漂移,从节点自动升级为主节点,保证了高可用性。
7 twemproxy缺点
1、支持动态移除节点,但该移除节点的数据就丢失了。
2、动态增加节点的时候,twemproxy不会对已有数据做重分布,这个需要自己写个脚本实现。
3、性能上的损耗,其实作为代理必定会有损耗,twemproxy损耗属于很小的级别了。
4、不支持针对多个值的操作,比如取sets的子交并补等(MGET 和 DEL 除外)。
5、不支持Redis的事务操作。
6、出错提示还不够完善。
最后编辑:Jeebiz 更新时间:2024-08-16 11:44