Redis數據庫與傳統數據庫屬於並行關係,也就是說傳統的關係型數據庫保存的是結構化數據,而Redis保存的是一些所謂的 臨時
數據,由於Redis具有一項很強的功能 持久化數據
,發現Redis好像也能夠作一些傳統數據庫的開發。可是如今Redis除了能夠進行數據的存儲以外,實際上也能夠在一些系統的架構設計之中做爲數據的緩衝點:
若是要想實現主從模式的配置,首先必定要準備出三臺Redis實例,本次爲了方便將在一臺主機上進行模擬,也就是說在這一臺主機上將準備出三個Redis實例,分別對應的端口爲:637九、6380、6381,其中6379運行的Redis服務爲主服務,而其它兩個端口運行的服務爲從服務。css
1.若是要想進行主從的模式匹配,主服務器上不須要作出任何的變化,也就是說主服務器根本就不關心是否有從服務器;java
2.全部的從服務的配置文件redis-6380.conf、redis-6381.conf必需要求明確的設置出它對應的主服務器。linux
vim /usr/local/redis/conf/redis-6380.conf
; slaveof 192.168.125.161 6379
masterauth mldnjava
3.啓動全部的Redis數據服務:nginx
/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6379.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6380.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6381.conf
4.登陸6379端口的Redis服務主服務查看全部的副本信息:git
/usr/local/redis/bin/redis-cli -h 192.168.125.161 -p 6379 -a mldnjava info replication
connected_slaves:2 slave0:ip=192.168.125.161,port=6380,state=online,offset=99,lag=0 slave1:ip=192.168.125.161,port=6381,state=online,offset=99,lag=0
若是能夠發現以上的信息就表示如今6379下有兩個從節點。github
5.操做主節點6379的數據:set mldn java
redis
get mldn
; (error) READONLY You can't write against a read only slave.
。備註:
主從設計的最大好處在於:能夠自動對數據作備份; 主從設計模式的最大缺點在於:只可以作備份,而出現災難以後沒法當即恢復。算法
只要是進行高可用的架構部署,那麼就必須保證多節點,在Redis裏面使用了主從模式能夠實現多節點配置,可是傳統的主從模式的設計有一個缺陷:一旦Master主機出現了問題以後,兩臺Slave主機將沒法提供正常的工做支持,例如:slave主機爲只讀主機,並且若是要想繼續提供支持,那麼你至少應該經過剩餘的幾臺slave裏面去推選出一個新的master,而且最爲重要的是,這個新的master還必須可以被用戶的程序找到。
哨兵機制(Sentinel)
Redis哨兵是redis官方推薦的redis高可用(HA)解決方案之一;spring
sentinel的功能:
監控(Monitoring),sentinel時刻監控着redis master-slave 是否正常運行;
通知(Notification),sentinel 能夠經過api來通知管理員,被監控的 redis master-slave 出現了問題;
自動故障轉移(Automatic failover),當redis master出現故障不可用狀態,sentinel 會開始一次故障轉移,將其中一個slave 提高爲新的 master ,將其餘的 slave 將從新配置使用新的 master 同步,並使用redis 的服務器應用程序在鏈接時受到使用新的地址鏈接;
配置提供者(Configuration provider),sentinel 做爲在集羣中的權威來源,客戶端鏈接到 sentinel 來獲取某個服務的當前 redis 主服務器的地址和其餘信息。當前故障轉移發生時,sentinel 會報告新地址。sql
1.若是要想進行哨兵配置及使用,請確保你的主機上已經準備好了Redis服務,本次將在一臺主機上模擬哨兵機制,如今的實現原則:一臺主機運行三個哨兵,而且該哨兵運行端口不一樣,可是這三個哨兵都要去監控同一個master的地址。
/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6379.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6380.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6381.conf
2.經過redis源代碼拷貝出哨兵運行程序: cp /usr/local/src/redis-3.2.9/src/redis-sentinel /usr/local/redis/bin/
3.全部的哨兵若是要想運行必定要準備出一個配置文件:sentinel.conf;
/usr/local/src/redis-3.2.9/sentinel.conf
;4.創建sentinel-26379.conf配置文件:vim /usr/local/redis/conf/sentinel-26379.conf
;
mkdir -p /usr/data/redis/{sentinel-26379,sentinel-26380,sentinel-26381}
;配置哨兵監聽端口:port 26379
配置哨兵的工做目錄:dir /usr/data/redis/sentinel-26379
設置監控的master:sentinel monitor mymaster 192.168.125.161 6379 2
備註:
設置的mymaster只是一個表明名稱,若是你一個哨兵監控多個master,則這個名稱必定要有所不一樣,然後2
表示若是有兩個哨兵認爲你出現了問題,則你應該下線選舉出新的master
設置master的認證信息:sentinel auth-pass mymaster mldnjava
設置master不活躍的時間:sentinel down-after-milliseconds mymaster 30000
選舉新的master失敗時間:sentinel failover-timeout mymaster 180000
只有一個master同步:sentinel parallel-syncs mymaster 1
撤銷Redis保護模式:protected-mode no
隨後按照這樣的配置分別創建sentinel-26380.conf、sentinel-26381.conf兩個配置文件。
cp /usr/local/redis/conf/sentinel-26379.conf /usr/local/redis/conf/sentinel-26380.conf cp /usr/local/redis/conf/sentinel-26379.conf /usr/local/redis/conf/sentinel-26381.conf
建議將此時的配置作一個副本保留一下:cp /usr/local/redis/conf/* /usr/data/redis/back/
5.啓動三個哨兵進程:
/usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel-26379.conf /usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel-26380.conf /usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel-26381.conf
經過哨兵的信息輸出能夠發現以下特色:
+slave
:當一個哨兵啓動以後若是已經肯定能夠鏈接到了master節點,則自動追加全部的slave節點;+sentinel
:每當啓動一個新的哨兵進程後會自動進行哨兵增長的信息提示;6.直接kill掉當前監控的master主機,隨後會發現有以下提示信息:
+sdown master mymaster 192.168.125.161 6379
:當前的master主機已經下線了;+vote-for-leader
:進行從新的投票選舉;+slave-reconf-sent slave 192.168.125.161:6381
:從主機會自動修改redis.conf配置文件;+switch-master mymaster 192.168.125.161 6379 192.168.125.161 6380
:6380爲新的master;7.若是此時的6379的進程又從新啓動成功了,那麼這個時候能夠考慮經過命令作一個從的設置,必定要求設置好redis-6379.conf配置文件中的masterauth屬性,若是不進行此項配置則沒法鏈接到master主機。
如今爲止已經成功的實現了哨兵處理機制,可是對於程序的編寫依然須要注意一點,若是要進行哨兵的處理操做,那麼必定要求經過哨兵來取得可用的master地址。
package cn.mldn.jedis; import java.util.HashSet; import java.util.Set; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.JedisSentinelPool; public class JedisSentinel { public static final String MASTER_NAME = "mymaster" ; // 定義哨兵的Master配置名稱 public static final int TIMEOUT = 2000 ; // 鏈接超時時間 public static final String REDIS_AUTH = "mldnjava" ; // 認證密碼 public static final int MAX_TOTAL = 1000 ; // 設置最大鏈接數 public static final int MAX_IDLE = 200 ; // 設置最小維持鏈接數 public static final int MAX_WAIT_MILLIS = 1000 ; // 設置最大等待時間 public static void main(String[] args) { // 若是要經過哨兵機制進行Redis訪問,那麼必需要明確的設置出全部可使用的哨兵的地址與端口 Set<String> sentinels = new HashSet<String>() ; // 設置全部的哨兵的處理地址信息 sentinels.add("192.168.125.161:26379") ; // 哨兵的地址 sentinels.add("192.168.125.161:26380") ; // 哨兵的地址 sentinels.add("192.168.125.161:26381") ; // 哨兵的地址 // 首先若是要想使用Jedis鏈接池,則必須有一個類能夠保存全部鏈接池相關屬性的配置項 JedisPoolConfig poolConfig = new JedisPoolConfig() ; poolConfig.setMaxTotal(MAX_TOTAL); // 設置最大鏈接數 poolConfig.setMaxIdle(MAX_IDLE); // 設置空閒的鏈接數 poolConfig.setMaxWaitMillis(MAX_WAIT_MILLIS);// 最大等待時間 // 此時全部的鏈接應該經過哨兵機制取得,因此這個時候應該使用JedisSentinelPool對象 JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, poolConfig); // 創建一個哨兵的鏈接池 Jedis jedis = pool.getResource() ; // 經過鏈接池獲取鏈接對象 jedis.auth(REDIS_AUTH) ; System.out.println(jedis); jedis.set("mldn", "www.mldn.cn") ; jedis.close(); pool.close(); // 關閉鏈接池 } }
在以前使用的SpringData進行Redis訪問的時候採用的是一個Spring內部支持的鏈接池,而且只有一個鏈接地址,可是若是要進行哨兵的配置,則須要將全部的哨兵地址都進行配置。
1.修改redis.properties配置文件,追加全部的哨兵配置地址:
# 追加全部的哨兵的訪問處理地址以及對應的端口號 redis.sentinel-1.host=192.168.68.165 redis.sentinel-2.host=192.168.68.165 redis.sentinel-3.host=192.168.68.165 redis.sentinel-1.port=26379 redis.sentinel-2.port=26380 redis.sentinel-3.port=26381 # 定義哨兵的master的名稱 redis.sentinel.master.name=mymaster # Redis的認證信息,認證信息密碼 redis.password=mldnjava # Redis鏈接的超時時間 redis.timeout=2000 # 設置最大的可用鏈接數 redis.pool.maxTotal=100 # 最小維持的可用鏈接數 redis.pool.maxIdle=20 # 最大等待時間 redis.pool.maxWaitMillis=2000
2.修改spring-redis.xml配置文件,在這個配置文件裏面須要將以前的鏈接池作一些更改:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd"> <!-- 若是要進行Redis處理用戶應該不去關注具體的序列化或反序列化操做,這一切都應該交給SpringData處理 --> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <!-- 定義Redis鏈接工廠 --> <property name="keySerializer"> <!-- 定義序列化Key的程序處理類 --> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="valueSerializer"> <!-- 處理value數據的操做 --> <!-- 明確表示若是要進行value數據保存的時候,保存的對象必定要使用JDK提供的序列化處理類 --> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/> </property> <property name="hashValueSerializer"> <!-- 處理hash數據的保存 --> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/> </property> </bean> <!-- 進行全部的哨兵地址的配置項 --> <bean id="sentinelsConfiguration" class="org.springframework.data.redis.connection.RedisSentinelConfiguration"> <property name="master"><!-- 配置master的節點名稱 --> <bean class="org.springframework.data.redis.connection.RedisNode"> <!-- 經過資源文件讀取出master的名稱進行配置 --> <property name="name" value="${redis.sentinel.master.name}"/> </bean> </property> <!-- 配置全部哨兵的鏈接地址信息 --> <property name="sentinels"> <set> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel-1.host}"/> <constructor-arg name="port" value="${redis.sentinel-1.port}"/> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel-2.host}"/> <constructor-arg name="port" value="${redis.sentinel-2.port}"/> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="${redis.sentinel-3.host}"/> <constructor-arg name="port" value="${redis.sentinel-3.port}"/> </bean> </set> </property> </bean> <!-- 首先進行Jedis鏈接池的相關配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="${redis.pool.maxTotal}"/> <!-- 最大可用鏈接數 --> <property name="maxIdle" value="${redis.pool.maxIdle}"/> <!-- 最小維持鏈接數 --> <property name="maxWaitMillis" value="${redis.pool.maxWaitMillis}"/> <!-- 最大等待時間 --> </bean> <!-- 進行ConnectionFactory的配置 --> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <constructor-arg name="sentinelConfig" ref="sentinelsConfiguration"/> <property name="poolConfig" ref="jedisPoolConfig"/> <!-- 引用進行鏈接池的配置項 --> <property name="password" value="${redis.password}"/> <!-- 定義的是鏈接密碼,認證密碼 --> </bean> </beans>
無論你如今電腦性能有多好,只要你運行了Redis,那麼就有可能形成一種很是可怕局面:你電腦的內存將馬上被佔滿,並且一臺Redis數據庫的性能終歸是有限制的,那麼如今若是要求保證用戶的執行速度快,就須要使用集羣的設計。而對於集羣的設計主要的問題就是解決單實例Redis的性能瓶頸。
Twemproxy是一個專門爲了這種nosql數據庫設計的一款代理工具軟件,這個工具軟件最大的特徵是能夠實現數據的分片處理。所謂的分片指的是根據必定的算法將要保存的數據保存到不一樣的節點之中。
有了分片以後數據的保存節點就可能有無限多個,可是理論上若是要真進行集羣的搭建,每每要求三臺節點起步。
Twemproxy
Twemproxy 的特性
最主要功能:用戶再也不直接操做真正的Redis,並且支持高性能的數據訪問,並且支持分片處理,能夠操做Redis集羣。
本次預計使用三臺Redis服務器,而且考慮到實際的應用環境,這三臺的Master分別有各自的兩個slave主機。因而如今給出本次使用的主機列表:
主機名稱 | IP地址 | 描述 |
---|---|---|
tw-redis-server-a | 192.168.125.162 | Reids master數據服務:6379 Reids slave數據服務:6380 Reids slave 數據服務:6381 |
tw-redis-server-b | 192.168.125.163 | Reids master 數據服務:6379 Reids slave 數據服務:6380 Reids slave 數據服務:6381 |
tw-redis-server-c | 192.168.125.164 | Reids master 數據服務:6379 Reids slave 數據服務:6380 Reids slave 數據服務:6381 |
1.tw-redis-server-*考慮到主機的通用性,全部的主機都建議修改主機名稱以及對應的hosts文件:
vim /etc/hostname
,修改完成以後從新啓動;vim /etc/hosts
,作好ip地址與主機名稱的映射;2.tw-redis-server-a本次主機經過以前的配置得來裏面已經實現了基本的配置環境,可是依然須要由用戶本身來配置主從關係:
vim /usr/local/redis/conf/redis-6380.conf
slaveof 192.168.125.162 6379 masterauth mldnjava
vim /usr/local/redis/conf/redis-6381.conf
slaveof 192.168.125.162 6379 masterauth mldnjava
3.tw-redis-server-*啓動全部Redis數據庫的實例
/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6379.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6380.conf /usr/local/redis/bin/redis-server /usr/local/redis/conf/redis-6381.conf
此時就至關於有就臺Redis數據庫,然後有三臺是Master節點,六臺爲Slave節點。
4.tw-redis-server-*查看從節點狀態:
/usr/local/redis/bin/redis-cli -h 192.168.125.162 -p 6379 -a mldnjava info replication
一臺主機的redis客戶端,只要你鏈接的ip、端口、密碼正確,那麼均可以鏈接到任意的主機上。
如今關鍵的問題就在於如何進行Redis分片處理,而分片處理的關鍵工具就是twemproxy工具,可是此工具給出的是一個源代碼,因此使用以前必定要先進行編譯處理。
1.tw-proxy-server-a將twemproxy-0.4.1.tar.gz源代碼開發包上傳到Linux系統之中,隨後將其解壓縮到源代碼目錄:
tar xzvf /srv/ftp/twemproxy-0.4.1.tar.gz -C /usr/local/src/
2.tw-proxy-server-a進入到源代碼所在的目錄:cd /usr/local/src/twemproxy-0.4.1/
autoreconf -fvi
;mkdir -p /usr/local/twemproxy
;./configure --prefix=/usr/local/twemproxy
;make && make install
;3.tw-proxy-server-a隨後須要配置一個twemproxy的配置文件,這個配置文件考慮到隨後與其它機制的整合,名稱必定要設置爲 redis_master.conf
:
mkdir -p /usr/local/twemproxy/conf
;cp /usr/local/src/twemproxy-0.4.1/conf/nutcracker.yml /usr/local/twemproxy/conf/redis_master.conf
4.tw-proxy-server-a編輯redis_master.conf文件:vim /usr/local/twemproxy/conf/redis_master.conf
redis_master: listen: 0.0.0.0:22121 hash: fnv1a_64 distribution: ketama auto_eject_hosts: true redis: true redis_auth: mldnjava server_retry_timeout: 2000 server_failure_limit: 1 servers: - 192.168.125.162:6379:1 - 192.168.125.163:6379:1 - 192.168.125.164:6379:1
以上配置的 redis_master
的名稱與配置文件是同樣的,並且必須同樣,同時在本文件裏面配置了redis訪問密碼,以及twemproxy全部可能代理到的redis服務器master節點。
5.tw-proxy-server-a{坑}twemproxy自己自帶有一個配置文件的檢測工具:
/usr/local/twemproxy/sbin/nutcracker -t /usr/local/twemproxy/conf/redis_master.conf
6.tw-proxy-server-a啓動twemproxy的服務:
mkdir -p /usr/local/twemproxy/{pid,logs}
/usr/local/twemproxy/sbin/nutcracker -c /usr/local/twemproxy/conf/redis_master.conf -p /usr/local/twemproxy/pid/redis_master.pid -o /usr/local/twemproxy/logs/redis_master.log -d
7.tw-proxy-server-a這個時候一旦twemproxy
啓動以後就表示該進程是一個redis
的代理進程, 全部的服務能夠經過twemproxy
訪問,而它的地址是:22121
,隨意找到一個redis
客戶端便可。 /usr/local/redis/bin/redis-cli -h 192.168.68.170 -p 22121 -a mldnjava
如今鏈接的直接爲代理,隨後找到各自的redis數據庫的服務。 /usr/local/redis/bin/redis-cli -h 192.168.68.167 -p 6379 -a mldnjava
8.編寫java程序經過jedis訪問:
package cn.mldn.jedis; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class TwemproxyDemo { public static final String REDIS_HOST = "192.168.68.170" ; // 主機地址 public static final int REDIS_PORT = 22121 ; // 端口號 public static final int TIMEOUT = 2000 ; // 鏈接超時時間 public static final String REDIS_AUTH = "mldnjava" ; // 認證密碼 public static final int MAX_TOTAL = 1000 ; // 設置最大鏈接數 public static final int MAX_IDLE = 200 ; // 設置最小維持鏈接數 public static final int MAX_WAIT_MILLIS = 1000 ; // 設置最大等待時間 public static final boolean TEST_ON_BORROW = true ; // 是否進行可用測試 public static void main(String[] args) { // 首先若是要想使用Jedis鏈接池,則必須有一個類能夠保存全部鏈接池相關屬性的配置項 JedisPoolConfig poolConfig = new JedisPoolConfig() ; poolConfig.setMaxTotal(MAX_TOTAL); // 設置最大鏈接數 poolConfig.setMaxIdle(MAX_IDLE); // 設置空閒的鏈接數 poolConfig.setMaxWaitMillis(MAX_WAIT_MILLIS);// 最大等待時間 poolConfig.setTestOnBorrow(TEST_ON_BORROW); // 是否要進行鏈接測試,以保證返回的鏈接爲可用鏈接 JedisPool pool = new JedisPool(poolConfig,REDIS_HOST,REDIS_PORT,TIMEOUT,REDIS_AUTH) ; Jedis jedis = pool.getResource() ; // 經過鏈接池獲取鏈接對象 for (int x = 0 ; x < 1000 ; x ++) { jedis.set("mldn-" + x, "www.mldn.cn") ; } jedis.close(); pool.close(); // 關閉鏈接池 } }
Twemproxy
若是要與Redis
集成使用的是Redis
的Master
節點,由於只有Master
節點才具有有寫功能,而全部的Slave節點只具有有隻讀的數據功能,如今的思考點暫時不放在twemproxy
上,而如今的問題集中在後端的全部Redis
節點之中,由於Redis
存在有主從關係,那麼一旦某一個Redis
的Master
被幹掉了,則必定要從新選舉出一個新的Master
節點,可是這個時候會出現有一個問題:twemproxy
所使用的配置文件是單獨存在的:
redis_master: listen: 0.0.0.0:22121 hash: fnv1a_64 distribution: ketama auto_eject_hosts: true redis: true redis_auth: mldnjava server_retry_timeout: 2000 server_failure_limit: 1 servers: - 192.168.125.162:6379:1 - 192.168.125.163:6379:1 - 192.168.125.164:6379:1
若是要進行哨兵機制運行至少須要有三臺或以上的主機,本次已經有了三臺Redis集羣,因此爲了方便,在以前的三臺主機上進行Sentinel配置,如今主機所運行的進程關係以下:
主機名稱 | IP地址 | 描述 |
---|---|---|
tw-redis-server-a | 192.168.125.162 | Redis服務637九、6380、6381 Sentinel服務 26379 |
tw-redis-server-b | 192.168.125.163 | Redis服務637九、6380、6381 Sentinel服務 26379 |
tw-redis-server-c | 192.168.125.164 | Redis服務637九、6380、6381 Sentinel服務 26379 |
tw-proxy-server-a | 192.168.125.165 | Twemproxy代理服務 Sentinel服務26379 |
1.tw-redis-server-*在全部的主機上創建哨兵機制的保存數據目錄:mkdir -p /usr/data/redis/sentinel
2.tw-redis-server-a進行哨兵配置文件的編寫:vim /usr/local/redis/conf/sentinel.conf
port 26379 dir /usr/data/redis/sentinel protected-mode no sentinel monitor redis_master_group1 192.168.125.162 6379 2 sentinel auth-pass redis_master_group1 mldnjava sentinel down-after-milliseconds redis_master_group1 10000 sentinel failover-timeout redis_master_group1 10000 sentinel parallel-syncs redis_master_group1 1 sentinel monitor redis_master_group2 192.168.125.163 6379 2 sentinel auth-pass redis_master_group2 mldnjava sentinel down-after-milliseconds redis_master_group2 10000 sentinel failover-timeout redis_master_group2 10000 sentinel parallel-syncs redis_master_group2 1 sentinel monitor redis_master_group3 192.168.125.164 6379 2 sentinel auth-pass redis_master_group3 mldnjava sentinel down-after-milliseconds redis_master_group3 10000 sentinel failover-timeout redis_master_group3 10000 sentinel parallel-syncs redis_master_group3 1
3.tw-redis-server-a將哨兵的配置文件發送到其它主機上:
拷貝到 tw-redis-server-b
主機:scp /usr/local/redis/conf/sentinel.conf 192.168.125.163:/usr/local/redis/conf/
拷貝到 tw-redis-server-c
主機:scp /usr/local/redis/conf/sentinel.conf 192.168.125.164:/usr/local/redis/conf/
4.tw-redis-server-*考慮到哨兵機制運行以後會進行配置文件的變動,那麼最好的作法是將這些配置文件作一個副本,這樣測試起來會比較方便:cp /usr/local/redis/conf/* /usr/data/redis/back/
5.tw-redis-server-*啓動哨兵進程:/usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel.conf
若是要想在twemproxy
之中與哨兵整合,而且實現twemproxy
進程的從新啓動,那麼有一個前提必須有保證:你的twemproxy
運行的主機必定要提供有哨兵機制,目的是爲了與其它的哨兵進行整合處理。
1.tw-redis-server-a將哨兵的配置文件拷貝到tw-proxy-server-a主機上;
scp /usr/data/redis/back/sentinel.conf 192.168.68.170:/usr/local/redis/conf;
2.tw-proxy-server-a經過源代碼文件拷貝出哨兵進程的啓動項:cp /usr/local/src/redis-3.2.9/src/redis-sentinel /usr/local/redis/bin/
3.tw-proxy-server-a啓動哨兵機制,這個哨兵機制是爲了讓Shell腳本能夠整合到全部的哨兵機制裏;
/usr/local/redis/bin/redis-sentinel /usr/local/redis/conf/sentinel.conf
4.tw-proxy-server-a爲了方便進行shell腳本的保存在twemproxy程序目錄中建立有一個sh的目錄:mkdir -p /usr/local/twemproxy/sh
5.tw-proxy-server-a創建一個能夠進行哨兵重啓twemproxy進程的shell腳本:
編輯命令:vim /usr/local/twemproxy/sh/client-reconfig.sh
#!/bin/sh # monitor_name="$1" master_old_ip="$4" master_old_port="$5" master_new_ip="$6" master_new_port="$7" twemproxy_name=$(echo $monitor_name |awk -F'_' '{print $1"_"$2}') twemproxy_bin="/usr/local/twemproxy/sbin/nutcracker" twemproxy_conf="/usr/local/twemproxy/conf/${twemproxy_name}.conf" twemproxy_pid="/usr/local/twemproxy/pid/${twemproxy_name}.pid" twemproxy_log="/usr/local/twemproxy/logs/${twemproxy_name}.log" twemproxy_cmd="${twemproxy_bin} -c ${twemproxy_conf} -p ${twemproxy_pid} -o ${twemproxy_log} -d" sed -i "s/${master_old_ip}:${master_old_port}/${master_new_ip}:${master_new_port}/" ${twemproxy_conf} ps -ef |grep "${twemproxy_cmd}" |grep -v grep |awk '{print $2}'|xargs kill ${twemproxy_cmd} sleep 1 ps -ef |grep "${twemproxy_cmd}" |grep -v grep
6.tw-proxy-server-a爲腳本授予所有執行權限:chmod 777 /usr/local/twemproxy/sh/client-reconfig.sh
7.tw-proxy-server-a如今要鏈接本機的哨兵進程,這樣才能夠與此腳本文件有關聯:
/usr/local/redis/bin/redis-cli -h 192.168.125.162 -p 26379 sentinel set redis_master_group1 client-reconfig-script /usr/local/twemproxy/sh/client-reconfig.sh /usr/local/redis/bin/redis-cli -h 192.168.125.162 -p 26379 sentinel set redis_master_group2 client-reconfig-script /usr/local/twemproxy/sh/client-reconfig.sh /usr/local/redis/bin/redis-cli -h 192.168.125.162 -p 26379 sentinel set redis_master_group3 client-reconfig-script /usr/local/twemproxy/sh/client-reconfig.sh
那麼此時哨兵機制一旦發生了從新的選舉以後,那麼會馬上從新啓動twemproxy的相關進程。
8.tw-redis-server-a殺死掉redis-6379服務進程,這樣master就消失了,消失以後應該會觸發腳本,會從新配置redis_master.conf文件,這個時候對應在twemproxy主機上的哨兵會自動進行twemproxy的進程從新啓動,以此保證twemproxy中Redis主機的高可用狀態。
Twemproxy主要功能在於數據的分片處理,並且會發如今整個的Redis集羣裏面,若是用戶要想訪問Redis集羣必須經過Twemproxy,因而這個時候就有可能形成一種問題:
HAProxy:haproxy是一個開源的,高性能的,基於TCP第四層和http第七層應用的千萬級高併發負載均衡軟件;
HAProxy優勢:
如今爲了觀察問題準備出來了三臺twemproxy主機,然後如今再須要準備出一臺haproxy主機tw-haproxy-server-a。然後經過這個haproxy主機先進行haproxy運行的處理。
1.tw-haproxy-server-a將haproxy
的開發包上傳到系統之中,隨後爲其進行解壓縮控制:tar xzvf /srv/ftp/haproxy-1.5.18.tar.gz -C /usr/local/src/
2.tw-haproxy-server-a進入到haproxy源代碼目錄:cd /usr/local/src/haproxy-1.5.18/
Haproxy
編譯後的保存目錄:mkdir -p /usr/local/haproxy
HAProxy
的處理必定要選擇好你當前的系統架構的信息:make TARGET=linux26 PREFIX=/usr/local/haproxy ARCH=x86_64
make install PREFIX=/usr/local/haproxy
;安裝完成以後會在 /usr/local/haproxy
目錄下存在有:doc、sbin、share三個目錄;
3.tw-haproxy-server-a創建一個haproxy的數據保存工做目錄:mkdir -p /usr/data/haprox
4.tw-haproxy-server-a經過源代碼拷貝出一個配置文件到指定的目錄之中;
cp /usr/local/src/haproxy-1.5.18/examples/haproxy.cfg /usr/local/haproxy/
5.tw-haproxy-server-a編輯 haproxy.cfg
配置文件:vim /usr/local/haproxy/haproxy.cfg
global
log 127.0.0.1 local0 log 127.0.0.1 local1 notice #log loghost local0 info maxconn 4096 chroot /usr/local/haproxy pidfile /usr/data/haproxy/haproxy.pid uid 99 gid 99 daemon #debug #quiet defaults log global mode tcp option httplog option dontlognull retries 3 redispatch maxconn 2000 contimeout 5000 clitimeout 50000 srvtimeout 50000 listen appli1-rewrite 0.0.0.0:10001 cookie SERVERID rewrite balance roundrobin option abortonclose option redispatch retries 3 maxconn 2000 timeout connect 5000 timeout client 50000 timeout server 50000 listen proxy_status bind :16001 mode tcp balance roundrobin server tw_proxy_1 192.168.125.165:22121 check inter 10s server tw_proxy_2 192.168.125.166:22121 check inter 10s server tw_proxy_3 192.168.125.167:22121 check inter 10s frontend admin_stats bind :7777 mode http stats enable option httplog maxconn 10 stats refresh 30s stats uri /admin stats auth mldn:java stats hide-version stats admin if TRUE
6.tw-haproxy-server-a須要進行haproxy的進程啓動:
/usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.cfg
7.若是如今要想確認當前已經正常啓動,則能夠經過管理控制檯查看:http://192.168.125.165:7777/admin
1.若是要想正常完成測試,必定要先保證Redis、sentinel、twemproxy的服務進程所有正常啓動;
ps -ef | grep redis
cp /usr/data/redis/back/sentinel.conf /usr/local/redis/conf/
/usr/local/redis/bin/redis-server /usr/local/redis/conf/sentinel.conf
2.tw-proxy-server-*啓動twemproxy的進程:
/usr/local/twemproxy/sbin/nutcracker -c /usr/local/twemproxy/conf/redis_master.conf -p /usr/local/twemproxy/pid/redis_master.pid -o /usr/local/twemproxy/logs/redis_master.log -d
3.先保證各個 twemproxy
的節點能夠正常使用。
4.使用haproxy進行代理操,使用redis客戶端登陸:/usr/local/redis/bin/redis-cli -h 192.168.125.167 -p 16001 -a mldnjava
5.經過jedis的java客戶端進行數據訪問:
package cn.mldn.jedis; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class TwemproxyDemo { public static final String REDIS_HOST = "192.168.125.167" ; // 主機地址 public static final int REDIS_PORT = 16001 ; // 端口號 public static final int TIMEOUT = 2000 ; // 鏈接超時時間 public static final String REDIS_AUTH = "mldnjava" ; // 認證密碼 public static final int MAX_TOTAL = 1000 ; // 設置最大鏈接數 public static final int MAX_IDLE = 200 ; // 設置最小維持鏈接數 public static final int MAX_WAIT_MILLIS = 1000 ; // 設置最大等待時間 public static void main(String[] args) { // 首先若是要想使用Jedis鏈接池,則必須有一個類能夠保存全部鏈接池相關屬性的配置項 JedisPoolConfig poolConfig = new JedisPoolConfig() ; poolConfig.setMaxTotal(MAX_TOTAL); // 設置最大鏈接數 poolConfig.setMaxIdle(MAX_IDLE); // 設置空閒的鏈接數 poolConfig.setMaxWaitMillis(MAX_WAIT_MILLIS);// 最大等待時間 JedisPool pool = new JedisPool(poolConfig,REDIS_HOST,REDIS_PORT,TIMEOUT,REDIS_AUTH) ; Jedis jedis = pool.getResource() ; // 經過鏈接池獲取鏈接對象 for (int x = 0 ; x < 10000 ; x ++) { jedis.set("mldn-" + x, "www.mldn.cn") ; } jedis.close(); pool.close(); // 關閉鏈接池 } }
若是此時的程序出現有以下的錯誤信息:
Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException: READONLY You can't write against a read only slave.
若是面對Redis
集羣,只是依靠twemproxy
的分片是不夠的,還須要有一系列的代理設計,例如:HAProxy能夠實現負載均衡設計。
Keepalived
是一個基於VRRP協議來實現的服務高可用方案,能夠利用其來避免IP單點故障,相似的工具還有heartbeat、corosync、pacemaker
。可是它通常不會單獨出現,而是與其餘負載均衡技術如lvs、haproxy、nginx一塊兒工做來達到集羣的高可用。
下載地址:http://wwww.keepalived.org/
keepalived組件給出的是一個源代碼的開發包,因此你依然須要在你的系統之中進行編譯與配置處理。
1.tw-haproxy-server-a主機將keepalived開發包上傳到Linux系統之中,隨後將其進行解壓縮。
tar xzvf /srv/ftp/keepalived-1.2.24.tar.gz -C /usr/local/
2.tw-haproxy-server-a主機爲了配置方便進行一下改名處理:
mv /usr/local/keepalived-1.2.24/ /usr/local/keepalived
3.tw-haproxy-server-a主機進入到keepalived組件包的目錄:cd /usr/local/keepalived/
4.tw-haproxy-server-a主機進行編譯處理:
./configure --prefix=/usr
make && make install
5.tw-haproxy-server-a主機將keepalived的配置文件拷貝到 /etc/keepalived
目錄之中;
mkdir -p /etc/keepalived
cp /usr/etc/keepalived/keepalived.conf /etc/keepalived/
6.tw-haproxy-server-a主機編輯keepalived.conf配置文件:vim /etc/keepalived/keepalived.conf
cat /proc/net/dev、ifconfig
,如今的名稱爲 ens33
;! Configuration File for keepalived global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 192.168.200.1 smtp_connect_timeout 30 router_id LVS_DEVEL vrrp_skip_check_adv_addr vrrp_strict vrrp_garp_interval 0 vrrp_gna_interval 0 } vrrp_instance VI_1 { state MASTER interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.68.250 } } virtual_server 192.168.125.250 16001 { delay_loop 6 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.125.168 16001 { weight 1 TCP_CHECK { connect_timeout 3 delay_before_retry 3 } } real_server 192.168.125.169 16001 { weight 1 TCP_CHECK { connect_timeout 3 delay_before_retry 3 } } }
7.tw-haproxy-server-b主機關閉 tw-haproxy-server-a
這臺虛擬機,然後將其克隆爲 tw-haproxy-server-b
主機。
8.tw-haproxy-server-b主機修改 keepalived.conf
配置文件,必定要設置爲BACKUP,同時優先級別必定要下降。
- 修改配置文件:vim /etc/keepalived/keepalived.conf
;
vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.68.250 } } virtual_server 192.168.125.250 16001 { delay_loop 6 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server 192.168.125.168 16001 { weight 1 TCP_CHECK { connect_timeout 3 delay_before_retry 3 } } real_server 192.168.125.169 16001 { weight 1 TCP_CHECK { connect_timeout 3 delay_before_retry 3 } } }
9.tw-haproxy-server-*啓動HAProxy:
/usr/local/haproxy/sbin/haproxy -f /usr/local/haproxy/haproxy.cfg
10.tw-haproxy-server-*啓動keepalived服務:service keepalived start
keepalived
相關進程:ps -ef | grep keepalived
keepalived
狀態:service keepalived status
keepalived
服務:service keepalived stop
11.此時若是在進行訪問,必定要使用VIP進行訪問。
haproxy
:http://192.168.125.250:7777/admin
;