一 应用场景描述

最近第三个游戏上线,游戏的热点数据是全部存在Redis数据库

二 twemproxy介绍

Twemproxy又叫做nutcracker,是一个为memcached和redis协议提供的快速而轻量的代理。它的最初设计是为了减少后端缓存服务器的连接数量。通过protocol pipeling and sharding使得可以横向扩展后端的缓存架构。

Twemproxy有以下几个特性:

  • Fast.

  • Lightweight.

  • Maintains persistent server connections.

  • Keeps connection count on the backend caching servers low.

  • Enables pipelining of requests and responses.

  • Supports proxying to multiple servers.

  • Supports multiple server pools simultaneously.

  • Shard data automatically across multiple servers.

  • Implements the complete  and  protocol.

  • Easy configuration of server pools through a YAML file.

  • Supports multiple hashing modes including consistent hashing and distribution.

  • Can be configured to disable nodes on failures.

  • Observability via stats exposed on the stats monitoring port.

  • Works with Linux, *BSD, OS X and SmartOS (Solaris)

在twemproxy中,进入的请求和出去的响应都是由mbuf分配内存的。mbuf可以实现零拷贝zero-copy。因为从客户端接收的请求和将请求转发到后端服务器使用的是同一个缓冲区。同样存放从后端服务器返回的响应和将响应发送给客户端使用的也是同一个缓冲区。

另外,mbuf的内存是由重用池reuse pool来管理。也就是一旦mubf的内存被分配,将不会被释放,只是放回到reuse pool中。mbuf的大小和twemproxy所能支持的并发连接之间存在某种权衡关系。设置大的mbuf可以减小twemproxy在读取请求或者响应时调用read syscall的数量。然而,设置较大的mbuf时,每一个活动连接都将使用高达16K的缓冲区大小,当twemproxy在处理大量来自客户端的并发连接时,这将成为一个问题。如果打算使用twemproxy处理大量的并发连接,使用-m参数设置较小的mbuf如512字节。

每一个客户端连接消耗至少一个mbuf。服务一个请求需要建立两个连接,一个由客户端到代理,另一个由代理到后端server,所以我们需要两个mbuf。

对于一个可以分段的请求如 'get foo bar\r\n',可以分段成为 'get foo\r\n'和'get bar\r\n',将消耗两个用于请求的mbuf和两个用于响应的mbuf。所以一个可以分为N个分段的请求需要N*2个mbuf。mbuf设计的好处就是所有分配的内存都来自一个reuse pool。坏处就是一旦mbuf被分配内存,内存将不会被释放,因为一个空闲的mbuf总是被退回到reuse pool.

因此,如果nutcracker需要处理1000个客户端请求和100个服务器请求,那么它将消耗(max(1000,100)*2*mbuf-size)大小的内存。如果假设客户端发送non-pipelined请求,设置默认mbuf大小16K,那么nutcracker将消耗32M内存

进而,如果一个请求可以分为10个分段,内存将消耗到320M,如果处理10K请求,内存消耗将达到3.2G.如果不适用默认的mbuf大小16K,设置大小为512K,那么nutcrakcer处理1000个请求消耗的内存为

1000*2*512*10=10M

这就是为什么如果需要nutcracker处理大量的客户端请求或者有需要multi-get请求,需要将mbuf设置成为一个较小的值比如512字节

三 twemproxy安装使用

下载软件包

tar zxvf nutcracker-0.4.0.tar.gz 

cd nutcracker-0.4.0

mkdir -p /data/app_platform/twemproxy/conf

mkdir -p /data/app_data/twemproxy/logs/

./configure --prefix=/data/app_platform/twemproxy/       --enable-debug=log 

make&make install

cp conf/nutcracker.yml /data/app_platform/twemproxy/conf/

cp scripts/nutcracker.init /etc/init.d/nutcracker

chmod a+x /etc/init.d/nutcracker

useradd nutcracker -s /sbin/nologin

chkconfig --level 35 nutcracker on

chown -R nutcracker /data/app_data/twemproxy/logs/

在生产环境中最好将nutcrakcer的日志功能开启,需要在编译的时候加上--enable-debug=log,同时在启动nutcracker的时候将日志级别设置成为LOG_INFO即-v 6.

这里我们在启动脚本中设置

-d -c /data/app_platform/twemproxy/conf/nutcracker.yml -v 6 -o /data/app_data/twemproxy/logs/nutcrakcer.log

/etc/init.d/nutcracker的内容如下:

#! /bin/sh## chkconfig: - 55 45# description:  Twitter's twemproxy nutcracker# processname: nutcracker# config: /etc/sysconfig/nutcracker# Source function library.. /etc/rc.d/init.d/functionsUSER="nutcracker"OPTIONS="-d -c /data/app_platform/twemproxy/conf/nutcracker.yml  -v 6 -o /data/app_data/twemproxy/logs/nutcrakcer.log"#if [ -f /etc/sysconfig/nutcracker ];then#    . /etc/sysconfig/nutcracker#fi# Check that networking is up.if [ "$NETWORKING" = "no" ]then    exit 0fiRETVAL=0prog="nutcracker"start () {    echo -n $"Starting $prog: "    daemon --user ${USER} /data/app_platform/twemproxy/sbin/${prog} $OPTIONS    RETVAL=$?    echo    [ $RETVAL -eq 0 ] && touch /var/lock/subsys/${prog}}stop () {    echo -n $"Stopping $prog: "    killproc ${prog}    RETVAL=$?    echo    if [ $RETVAL -eq 0 ] ; then        rm -f /var/lock/subsys/${prog}    fi}restart () {    stop    start}# See how we were called.case "$1" in  start)    start    ;;  stop)    stop    ;;  status)    status ${prog}    ;;  restart|reload)    restart    ;;  condrestart)    [ -f /var/lock/subsys/nutcracker ] && restart || :    ;;  *)    echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"    exit 1esacexit $?

配置twemproxy

/data/app_platform/twemproxy/conf/nutcracker.yml

在源码包中的conf目录下有配置文件案例

在配置文件中可以配置多个server pool,每个server pool可以配置多个redis实例

gintama:  listen: 192.168.100.68:22124  hash: fnv1a_64  distribution: ketama  timeout: 100  redis: true  auto_eject_hosts: true  server_retry_timeout: 2000  server_failure_limit: 1  servers:    - 192.168.100.68:6379:1       - 192.168.100.68:6380:1       - 192.168.100.68:6381:1       - 192.168.100.69:6379:1       - 192.168.100.69:6380:1       - 192.168.100.69:6381:1

gintama是server pool的名称

listen   监听的服务器IP和端口,可以是一个socket的绝对路径如/var/run/nutcracker.sock

hash算法名称,可以的值有

  • one_at_a_time

  • md5

  • crc16

  • crc32 (crc32 implementation compatible with )

  • crc32a (correct crc32 implementation as per the spec)

  • fnv1_64

  • fnv1a_64

  • fnv1_32

  • fnv1a_32

  • hsieh

  • murmur

  • jenkins

hash_tag  指定hash_tag可以将不同的key值映射到相同的服务器上。它将key值的一部分用来计算hash值。

distribution    指定key值得分布模式,可以有的值为:

  • ketama

  • modula

  • random

timeout    设置等待和后端缓存服务器建立连接或者等待后端缓存服务器返回响应的超时时间,默认无线等待下去

redis     使用redis协议

redis_auth  使用redis验证

auto_eject_hosts   设置是否将一个尝试了server_failure_limit设置的次数后,仍然无法连接的服务器从server pool中临时移除。

server_retry_timeout 设置尝试重新连接被临时移除的服务器的超时时间,默认是30000毫秒

server_failure_limit  如果连续连接次数达到设置的数字,就将这个server从pool中临时移除

servers      指定后端缓存服务器的IP,端口和权重

测试配置文件语法:

/data/app_platform/twemproxy/sbin/nutcracker -t -c /data/app_platform/twemproxy/conf/nutcracker.yml 

参考地址: