一 应用场景描述
最近第三个游戏上线,游戏的热点数据是全部存在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 memcached ascii and redis 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安装使用
从https://drive.google.com/folderview?id=0B6pVMMV5F5dfMUdJV25abllhUWM&usp=drive_web
下载软件包
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/functions USER="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 0 fi RETVAL=0 prog="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 1 esac exit $?
配置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 libmemcached)
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
参考地址:
https://github.com/twitter/twemproxy