首頁  >  文章  >  資料庫  >  Redis資料分片如何實現

Redis資料分片如何實現

王林
王林轉載
2023-06-03 09:05:251283瀏覽

Twemproxy的介紹

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。

Twemproxy的優點:

1)對外暴露一個存取節點,減少程式複雜度。

2)支援失敗節點自動刪除,可以設定重新連接該節點的時間,可以設定連接多少次之後刪除該節點,該方式適合作為cache存儲,不然會丟失Key;

3)支援設定HashTag,透過HashTag可以自己設定將兩個KEYhash到同一個實例上去。

4)多種hash演算法,並且可以設定後端實例的權重。

5)減少與redis的直接連接數:保持與redis的長連接,可設定代理與後台每個redis連接的數目,自動分片到後端多個redis實例上。

6)避免單點問題:可以平行部署多個代理層,客戶端自動選擇可用的一個。

7)高吞吐量:連線重複使用,記憶體重複使用,將多個連線請求,組成redis pipelining統一向redis請求。

Twemproxy的缺點:

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使用架構

第一種:單節點Twemproxy

Redis資料分片如何實現

ps:節省硬體資源,但容易有單點故障。

第二種:高可用Twemproxy

Redis資料分片如何實現

#PS:浪費二分之一的資源,但是節點高可用。

第三種:負載平衡Twemproxy

Redis資料分片如何實現

#PS:如果你是大規模Redis或Memcached應用場景,就可以做Twemproxy的負載軍和場景,也就是在高可用Twemproxy的基礎上加LVS節點,利用LVS(Linux virtual server)做Twemproxy的負載平衡,LVS是四層負載平衡技術,有很強大的代理能力,具體可以看​​本部落格的LVS章節介紹。但當你使用LVS之後,又出現了Twemproxy的問題,單點故障故障問題,這個時候又要跟給LVS做高可用了。利用OSPF路由技術,LVS也可以實現負載平衡。而這個架構也就是我目前工作中正在使用的架構方式。

另外不管使用以上哪一種架構方式,都無法避免Redis的單點故障問題,Redis持久化也無法避免硬體故障問題。如果必須確保Redis資料存取的不可中斷性,那你還是使用Redis叢集模式吧,叢集模式目前對JAVA支援還不錯,工作中也有大量的使用。

安裝Twemproxy

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報錯就表示版本低了,需要編譯安裝了。

編譯安裝Autoconf

[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

編譯安裝Twemproxy

[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

Twemproxy新增設定檔

[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集群,只需要定义不同的配置段即可。

启动twemproxy (nutcracker)

刚已经加好了配置文件,现在测试下配置文件:

[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节点(想添加更多的也可以)。Twemproxy就是用上面的配置了,下面只需要增加两个Redis节点。

安装配置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

配置两个Redis节点

[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密码。

启动两个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读写数据

首先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存储到某个后端节点了。

如何Reload twemproxy?

Twemproxy没有为启动提供脚本,只能通过命令行参数启动。所以,无法使用对twemproxy进行reload的操作,在生产环境中,一个应用无法reload(重载配置文件)是一个灾难。当你对twemproxy进行增删节点时如果直接使用restart的话势必会影响线上的业务。所以最好的办法还是reload,既然twemproxy没有提供,那么可以使用kill命令带一个信号,然后跟上twemproxy主进程的进行号即可。

kill -SIGHUP PID

注意,PID就是twemproxy master进程。

以上是Redis資料分片如何實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除