Twitter的Twemproxy是目前市面上用的最廣的使用做多的用來做redis叢集服務。由於redis是單線程,而且官方的cluster 還不是很穩定和廣泛使用。 Twemproxy是一種代理分片機制,Twemproxy作為代理,可接受來自多個程序的訪問,按照路由規則,轉發給後台的各個Redis伺服器,再原路返回。此方案很好的解決了單一Redis實例承載能力的問題。當然,Twemproxy本身也是單點,需要用Keepalived做高可用方案(或LVS)。透過Twemproxy可以使用多台伺服器來水平擴張redis服務,可以有效的避免單點故障問題。雖然使用Twemproxy需要更多的硬體資源和在redis性能有一定的損失(twitter測試約20%),但是能夠提高整個系統的HA也是相當划算的。其實twemproxy不光實現了redis協議,還實現了memcached協議,什麼意思?換句話說,twemproxy不光可以代理redis,也可以代理memcached。
1)對外暴露一個存取節點,減少程式複雜度。
2)支援失敗節點自動刪除,可以設定重新連接該節點的時間,可以設定連接多少次之後刪除該節點,該方式適合作為cache存儲,不然會丟失Key;
3)支援設定HashTag,透過HashTag可以自己設定將兩個KEYhash到同一個實例上去。
4)多種hash演算法,並且可以設定後端實例的權重。
5)減少與redis的直接連接數:保持與redis的長連接,可設定代理與後台每個redis連接的數目,自動分片到後端多個redis實例上。
6)避免單點問題:可以平行部署多個代理層,客戶端自動選擇可用的一個。
7)高吞吐量:連線重複使用,記憶體重複使用,將多個連線請求,組成redis pipelining統一向redis請求。
1)不支援針對多個值的操作,例如取sets的子交並補等。
2)不支援Redis的事務操作。
3)對於已申請的記憶體不會釋放,所有機器記憶體要大,且需要定期重啟,不然就會出現客戶端連線錯誤。
4)不支援動態增刪節點,修改完組態需重新啟動。
5)改變節點時,系統不會對已有資料重分配,不自己寫腳本做資料遷移的話,會造成部分key遺失(key本身存在某redis上,只是key被哈希到了其他節點,造成“丟失”)。
6)權重直接影響key的雜湊結果,改變節點權重會造成部分key遺失。
7)預設Twemproxy是單執行緒運行,但是大部分使用Twemproxy的公司都會自行進行二次開發一下,改成多執行緒。
整體來說,twemproxy還是非常的可靠,雖然性能有損失,但是相對來說還是很值得的,而且久經考驗,使用非常廣泛。更多更詳細的資料請參考官方文件。另外twemproxy只適合靜態集群,不適合需要動態增刪節點,手動調整負載的場景,如果我們直接來用,需要做開發改進工作。 https://github.com/wandoulabs/codis這個系統是基於twemproxy,增加了動態資料遷移等功能,具體使用方法需要進一步測試。
第一種:單節點Twemproxy
ps:節省硬體資源,但容易有單點故障。
第二種:高可用Twemproxy
#PS:浪費二分之一的資源,但是節點高可用。
第三種:負載平衡Twemproxy
#PS:如果你是大規模Redis或Memcached應用場景,就可以做Twemproxy的負載軍和場景,也就是在高可用Twemproxy的基礎上加LVS節點,利用LVS(Linux virtual server)做Twemproxy的負載平衡,LVS是四層負載平衡技術,有很強大的代理能力,具體可以看本部落格的LVS章節介紹。但當你使用LVS之後,又出現了Twemproxy的問題,單點故障故障問題,這個時候又要跟給LVS做高可用了。利用OSPF路由技術,LVS也可以實現負載平衡。而這個架構也就是我目前工作中正在使用的架構方式。
另外不管使用以上哪一種架構方式,都無法避免Redis的單點故障問題,Redis持久化也無法避免硬體故障問題。如果必須確保Redis資料存取的不可中斷性,那你還是使用Redis叢集模式吧,叢集模式目前對JAVA支援還不錯,工作中也有大量的使用。
1、下載Twemproxy
請將以下語句重寫為一句話: 將 twemproxy 儲存庫複製到本機,使用以下指令:git clone https://github.com/twitter/twemproxy.git 重寫後: 在本機上使用以下指令 git clone https://github.com/twitter/twemproxy.git 複製 twemproxy 儲存庫
2、安裝Twemproxy
#Twemproxy需要使用Autoconf進行編譯設定。 GNU Autoconf是一個在Bourne shell下製作供編譯、安裝和包裝軟體的設定腳本的工具。 Autoconf並不受程式語言限制,常用於C、C 、Erlang和Objective-C。配置腳本控制了一個軟體包在特定係統上的安裝。透過進行一系列測試,配置腳本從模板生成了makefile和頭文件,並根據需要調整了軟體包,使其適用於特定的系統。 Autoconf, along with Automake and Libtool, form the GNU Build System.。 Autoconf由戴維·麥肯思於1991年夏天編寫用於支援他在自由軟體基金會的程式設計工作。 Autoconf已經整合了多個人編寫的改進程式碼,並成為了最廣泛使用的自由編譯配置軟體。
下面開始使用autoreconf對twemproxy編譯配置:
[root@www twemproxy]# autoreconfconfigure.ac:8: error: Autoconf version 2.64 or higher is required configure.ac:8: the top level autom4te: /usr/bin/m4 failed with exit status: 63 aclocal: autom4te failed with exit status: 63 autoreconf: aclocal failed with exit status: 63 [root@www twemproxy]# autoconf --versionautoconf (GNU Autoconf) 2.63
提示autoreconf 的版本過低,上面使用的是autoconf 2.63版本的,所以下面下載autoconf 2.69版本進行編譯安裝。注意如果你是CentOS6,那麼你的預設版本就是2.63,如果你是CentOS7,那麼你的預設版本應該是2.69,如果你是Debian8或Ubuntu16,那麼你的預設版本應該也是2.69。反正如果執行autoreconf報錯就表示版本低了,需要編譯安裝了。
[root@www ~]# wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz[root@www ~]# tar xvf autoconf-2.69.tar.gz[root@www ~]# cd autoconf-2.69[root@www autoconf-2.69]# ./configure --prefix=/usr[root@www autoconf-2.69]# make && make install[root@www autoconf-2.69]# autoconf --versionautoconf (GNU Autoconf) 2.69
[root@www ~]# cd /root/twemproxy/[root@www twemproxy]# autoreconf -fvi[root@www twemproxy]# ./configure --prefix=/etc/twemproxy CFLAGS="-DGRACEFUL -g -O2" --enable-debug=full[root@www twemproxy]# make && make install
如果autoreconf -fvi時報如下錯誤,就是要安裝libtool工具,需要依賴libtool(如果是CentOS直接使用yum install libtool即可,如果是Debian直接使用apt-get install libtool即可)。
autoreconf: Entering directory `.' autoreconf: configure.ac: not using Gettext autoreconf: running: aclocal --force -I m4 autoreconf: configure.ac: tracing autoreconf: configure.ac: adding subdirectory contrib/yaml-0.1.4 to autoreconf autoreconf: Entering directory `contrib/yaml-0.1.4'autoreconf: configure.ac: not using Autoconf autoreconf: Leaving directory `contrib/yaml-0.1.4' autoreconf: configure.ac: not using Libtool autoreconf: running: /usr/bin/autoconf --force configure.ac:36: error: possibly undefined macro: AC_PROG_LIBTOOL If this token and others are legitimate, please use m4_pattern_allow. See the Autoconf documentation. autoreconf: /usr/bin/autoconf failed with exit status: 1
[root@www twemproxy]# mkdir /etc/twemproxy/conf[root@www twemproxy]# cat /etc/twemproxy/conf/nutcracker.ymlredis-cluster: listen: 0.0.0.0:22122 hash: fnv1a_64 distribution: ketama timeout: 400 backlog: 65535 preconnect: true redis: true server_connections: 1 auto_eject_hosts: true server_retry_timeout: 60000 server_failure_limit: 3 servers: - 172.16.0.172:6546:1 redis01 - 172.16.0.172:6547:1 redis02
設定選項介紹:
redis-cluster:給這個設定段取一個名字,可以有多個組態段;
listen:設定監控IP和連接埠;
hash:具體的hash函數,支援md5,crc16,crc32,finv1a_32,fnv1a_64,hsieh,murmur,jenkins等十多種,一般選用fnv1a_64可以了,預設也是fnv1a_64;
重寫:使用hash_tag功能可以根據key的某個部分計算key的雜湊值。 hash_tag由兩個字元組成,一個是hash_tag的開始,另外一個是hash_tag的結束,在hash_tag的開始和結束之間,是將用於計算key的hash值的部分,計算的結果會用於選擇伺服器。例如:如果hash_tag被定義為”{}”,那麼key值為”user:{user1}:ids”和”user:{user1}:tweets”的hash值都是基於”user1”,最終會被映射到相同的伺服器。而”user:user1:ids”將會使用整個key來計算hash,可能會被映射到不同的伺服器。
distribution:指定哈希演算法,這個哈希演算法決定透過上面hash後的key如何分佈在多個server上,預設是」ketama「一致性哈希。 ketama:ketama一致性hash演算法,會根據伺服器建構出一個hash ring,並為ring上的節點分配hash範圍。 ketama的優點在於單一節點新增、刪除之後,會最大程度上保持整個群集中快取的key值可以被重複使用。 modula:modula很簡單,就是依照key值的hash值取模,依照取模的結果選擇對應的伺服器。 random:random是無論key值的hash是什麼,隨機的選擇一個伺服器作為key值操作的目標。
timeout:設定twemproxy的逾時時間,當timeout被設定後,如果在timeout的時間過後還沒有從服務端得到回應,這時會將超時錯誤訊息SERVER_ERROR Connection time out傳送給客戶端
backlog:監聽TCP的backlog(連線等待佇列)的長度,預設是512。
preconnect:指定是否在系統啟動時,twemproxy建立和所有redis的連接,預設是false,一個布林值;
redis:指定此配置段否作為Redis做代理,如果不加redis為true的話,就可以為memcached叢集做代理(這就是Twemproxy作為redis或memcached叢集代理的唯一區別);
redis_auth: 如果你的後端Redis開啟了認證,那麼就需要redis_auth指定認證的密碼了;
server_connections:twemproxy與每台redis伺服器的連線數,預設就是1,如果大於1,使用者指令可能會發到不同的連線上,可能造成指令的實際執行順序和使用者指定的不一致(類似並發);
auto_eject_hosts:是否在節點無法回應的時候剔除,預設為true,但需要注意,節點剔除後,因為機器數減少,機器雜湊位置變化,會造成部分key無法命中,但是不剔除程式連線就會報錯;
server_retry_timeout:控制伺服器連線的時間間隔,單位是毫秒,在auto_eject_host被設定為true的時候產生作用,預設是30000毫秒;
server_failure_limit:Redis连续超时的次数,超过这个次数就视其为无法连接,如果auto_eject_hosts设置为true,那么此Redis会被移除;
servers:一个pool中的服务器的地址、端口和权重的列表,包括一个可选的服务器的名字,如果提供服务器的名字,将会使用它决定server的次序,从而提供对应的一致性hash的hash ring。否则,将使用server被定义的次序,可以通过两种字符串格式指定’host:port:weight’或者’host:port:weight name’。一般都是使用第二种别名的方式,这样当其中某个Redis节点出现问题时,可以直接添加一个新的Redis节点但服务器名字不要改变,这样twemproxy还是使用相同的服务器名称进行hash ring,所以其他数据节点的数据不会出现问题(只有挂点的机器数据丢失)。
PS:要严格按照Twemproxy配置文件的格式来,不然就会有语法错误;另外,在Twemproxy的配置文件中可以同时设置代理Redis集群或Memcached集群,只需要定义不同的配置段即可。
刚已经加好了配置文件,现在测试下配置文件:
[root@www twemproxy]# /etc/twemproxy/sbin/nutcracker -tnutcracker: configuration file 'conf/nutcracker.yml' syntax is ok
说明配置文件已经成功,现在开始运行nutcracker:
[root@www ~]# /etc/twemproxy/sbin/nutcracker -c /etc/twemproxy/conf/nutcracker.yml -p /var/run/nutcracker.pid -o /var/log/nutcracker.log -d选项说明: -h, –help #查看帮助文档,显示命令选项;-V, –version #查看nutcracker版本;-c, –conf-file=S #指定配置文件路径 (default: conf/nutcracker.yml);-p, –pid-file=S #指定进程pid文件路径,默认关闭 (default: off);-o, –output=S #设置日志输出路径,默认为标准错误输出 (default: stderr);-d, –daemonize #以守护进程运行;-t, –test-conf #测试配置脚本的正确性;-D, –describe-stats #打印状态描述;-v, –verbosity=N #设置日志级别 (default: 5, min: 0, max: 11);-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);-m, –mbuf-size=N #设置mbuf块大小,以bytes单位 (default: 16384 bytes);
PS:一般在生产环境中,都是使用进程管理工具来进行twemproxy的启动管理,如supervisor或pm2工具,避免当进程挂掉的时候能够自动拉起进程。
[root@www ~]# ps aux | grep nutcrackerroot 20002 0.0 0.0 19312 916 ? Sl 18:48 0:00 /etc/twemproxy/sbin/nutcracker -c /etc/twemproxy/conf/nutcracker.yml -p /var/run/nutcracker.pid -o /var/log/nutcracker.log -d root 20006 0.0 0.0 103252 832 pts/0 S+ 18:48 0:00 grep nutcracker [root@www ~]# netstat -nplt | grep 22122tcp 0 0 0.0.0.0:22122 0.0.0.0:* LISTEN 20002/nutcracker
这里我们使用第一种方案在同一台主机上测试Twemproxy代理Redis集群,一个twemproxy和两个Redis节点(想添加更多的也可以)。Twemproxy就是用上面的配置了,下面只需要增加两个Redis节点。
在安装Redis之前,需要安装Redis的依赖程序tcl,如果不安装tcl在Redis执行make test的时候就会报错的哦。
[root@www ~]# yum install -y tcl[root@www ~]# wget https://github.com/antirez/redis/archive/3.2.0.tar.gz[root@www ~]# tar xvf 3.2.0.tar.gz -C /usr/local[root@www ~]# cd /usr/local/[root@www local]# mv redis-3.2.0 redis[root@www local]# cd redis[root@www redis]# make[root@www redis]# make test[root@www redis]# make install
[root@www ~]# mkdir /data/redis-6546[root@www ~]# mkdir /data/redis-6547[root@www ~]# cat /data/redis-6546/redis.confdaemonize yes pidfile /var/run/redis/redis-server.pid port 6546bind 0.0.0.0 loglevel notice logfile /var/log/redis/redis-6546.log [root@www ~]# cat /data/redis-6547/redis.confdaemonize yes pidfile /var/run/redis/redis-server.pid port 6547bind 0.0.0.0 loglevel notice logfile /var/log/redis/redis-6547.log
PS:简单提供两个Redis配置文件,如果开启了Redis认证,那么在twemproxy中也需要填写Redis密码。
[root@www ~]# /usr/local/redis/src/redis-server /data/redis-6546/redis.conf[root@www ~]# /usr/local/redis/src/redis-server /data/redis-6547/redis.conf[root@www ~]# ps aux | grep redisroot 23656 0.0 0.0 40204 3332 ? Ssl 20:14 0:00 redis-server 0.0.0.0:6546 root 24263 0.0 0.0 40204 3332 ? Ssl 20:16 0:00 redis-server 0.0.0.0:6547
首先twemproxy配置项中servers的主机要配置正确,然后连接Twemproxy的22122端口即可测试。
[root@www ~]# redis-cli -p 22122127.0.0.1:22122> set key vlaue OK 127.0.0.1:22122> get key"vlaue"127.0.0.1:22122> FLUSHALL Error: Server closed the connection 127.0.0.1:22122> quit
上面我们set一个key,然后通过twemproxy也可以获取到数据,一切正常。但是在twemproxy中使用flushall命令就不行了,不支持。
然后我们去找分别连接两个redis节点,看看数据是否出现在某一个节点上了,如果有,就说明twemproxy正常运行了。
[root@www ~]# redis-cli -p 6546127.0.0.1:6546> get key (nil) 127.0.0.1:6546>
由上面的结果我们可以看到,数据存储到6547节点上了。目前没有很好的办法明确知道某个key存储到某个后端节点了。
Twemproxy没有为启动提供脚本,只能通过命令行参数启动。所以,无法使用对twemproxy进行reload的操作,在生产环境中,一个应用无法reload(重载配置文件)是一个灾难。当你对twemproxy进行增删节点时如果直接使用restart的话势必会影响线上的业务。所以最好的办法还是reload,既然twemproxy没有提供,那么可以使用kill命令带一个信号,然后跟上twemproxy主进程的进行号即可。
kill -SIGHUP PID
注意,PID就是twemproxy master进程。
以上是Redis資料分片如何實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!