twemproxy是一个twtter开源的一个redis和memcache代理服务器,只用于简单的代理中间件的程序。
支持失败的节点自动摘除,可以设置连接多少次之后删除该节点,这种方式仅可用于将redis当缓存用的时候。
所有的key通过一致性哈希算法分布到集群中所有的redis实例中,多种可选hash算法。
减少客户端和redis实例的连接数,代理与每个redis实例维持长连接。
代理是无状态的,可以任意部署多套,避免单点问题,客户端任意连接一个都可以。
默认启用pipeline,连接复用,提高效率。
由于twemproxy本身只是简单的代理,所以需要依赖于一些其他的程序,部署的时候主要使用下图的架构:
后端redis集群分成若干个group,每个group有一个master节点和若干个slave节点。
使用 Redis Sentinel 管理主从备份,用于主从切换,当主服务器挂掉后,自动将从服务器提升为主服务器。
使用 Redis-Twemproxy Agent 与 Redis Sentinel 连接,监听主服务器切换的事件,并且立即更新 twemproxy的配置文件后重启。 twemproxy是无状态的,所以可以部署多个twemproxy,前端采用haproxy做负载均衡。
注:这里需要重启twemproxy,速度虽然很快,但是仍然会对现有服务造成一定影响,可以通过修改twemproxy源码来实现不用重启就可以自动连接到新的redis-master节点,需要时间进行二次开发。
由于twemproxy无状态的特性,可以在多个机器上部署多套,然后通过haproxy来进行负载均衡。
redis项目自带的用于主从切换的程序,配置较为简单,只需要配置需要监控的master-server即可,之后会通过协议获取到对应的所有slave-server,并在master挂掉后自动进行选举提升响应的slave为master。
redis-sentinel也可以是一个集群,避免单点故障。
用nodejs写的一个监控程序,用于监听 redis-sentinel 的master切换事件,并且及时更新twemproxy的配置文件后重新启动。
https://github.com/Stono/redis-twemproxy-agent.git
需要有nodejs的运行环境 yum install -y nodejs
需要npm包管理器 yum install -y npm
需要修改 lib/cli.js 中的相关配置,例如 cli.parse({ host: ['h', 'Redis sentinel hostname', 'string', '192.168.177.130'], port: ['p', 'Redis sentinel port number', 'number', 26379], config: ['f', 'Path to twemproxy config', 'path', '/etc/nutcracker.yml'], command: ['c', 'Command to restart twemproxy', 'string', '/etc/init.d/twemproxy restart'], log: ['l', 'The log file location', 'string', '/var/log/twemproxy/twemproxy_sentinel.log'] });
之后进入redis-twemproxy-agent目录, sudo npm install -g 安装即可
redis_twemproxy_agent直接启动,也可以通过 npm 安装 forever 来使nodejs程序在后台运行。
/etc/init.d/twemproxy restart, 可以写一个专门用于重启 twemproxy 的脚本。
前端多个 twemproxy 可以使用 haproxy 来进行负载均衡。
简单配置下即可
listen redis1 bind *:6379 mode tcp balance roundrobin server server1 192.168.177.130:6379 maxconn 1000 server server2 192.168.177.128:6379 maxconn 1000
和redis一样,具有很高的性能,redis的作者也提到twemproxy的性能损失在10%-20%,鉴于它的优点这样的损失是可以接受的。
通过增加后端的redis实例以及twemproxy的数量,可以增加系统的并发承载能力以及存储容量。
鉴于twemproxy也是单线程的,所以基本上twemproxy的数量可能需要和后端redis实例一样甚至更多才能充分发挥多实例的并发能力。
由于环境有限,这里简单进行了单机的测试。
测试命令: redis-benchmark -r 1048576 -c 100 -d 256 -t set,get,mset –csv -n 100000
redis单机 "SET","49751.24" "GET","49800.80" 使用twemproxy进行代理后测试 "SET","71633.23" "GET","71736.01"
这里提高的原因应该是twemproxy会用pipeline的方式往server端发送消息,所以反而会有一定提升。
理论上的效率损失在10% - 20%之间。
动态扩容(缺点)
如果需要动态增加redis机器的话比较麻烦,因为采用一致性哈希算法,增加一个机器后,原有的key的分布将会改变,会出现丢失key的问题。
这方面可以采用自己写脚本迁移数据的方式,不过比较繁琐,还会影响到当前服务的正常运行。
还有另外一种解决方案就是进行二次开发,据了解现在很多公司都是在twemproxy基础上进行二次开发,增加了对zookeeper的依赖,将redis节点信息以及hash域相关的数据存储在zookeeper上,然后增加动态迁移数据的模块,可以在不影响现有服务运行的情况下完成增删机器。
可设置状态监控ip和端口,访问ip和端口可以得到一个json格式的状态信息串,可设置监控信息刷新间隔时间,进行一些简单的监控。
总的来看,这一套方案可行性很高,基本上满足了绝大多数需求,可以在不进行二次开发的基础上实现大多数功能,成本很低。
但是考虑到以后可能的扩容情况,需要进行二次开发,短时间内可能很难达到一个理想的稳定状态。
直接通过c的源码编译安装。
编辑配置文件:
test: listen: 0.0.0.0:22121 hash: fnv1a_64 distribution: ketama auto_eject_hosts: true timeout: 400 redis: true server_retry_timeout: 2000 server_failure_limit: 1 servers: - 192.168.177.134:6379:1 - 192.168.177.135:6379:1 - 192.168.177.128:6379:1
之后在后台启动
nutcracker -d -c /etc/nutcracker.yml
通过 22121 端口就可以像使用单台redis一样来进行操作。