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  创建时间:2023-01-09 19:44
最后编辑:Jeebiz  更新时间:2024-08-16 11:44