複習電商筆記-31-redis哨兵
商品類目新增快取
1)將結果資料儲存到redis中,注意key的定義,不要太長,不要相同。將java物件序列化成json字串,同時可設定生存時間。
2)檢測快取中是否存在,如果存在就返回。不存在就直接去資料庫進行查詢。(如果有異常,要捕獲處理,不能影響正常業務邏輯)
修改ItemCatService.java檔案
package com.jt.manage.service; import java.io.IOException; import java.util.List; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.jt.common.service.RedisService; import com.jt.manage.mapper.ItemCatMapper; import com.jt.manage.pojo.ItemCat; @Service public class ItemCatService extends BaseService<ItemCat>{ @Autowired private ItemCatMapper itemCatMapper; @Autowired private RedisService redisService; //引入java物件和json串轉換物件ObjectMapper;全域性唯一 private static final ObjectMapper MAPPER = new ObjectMapper(); public List<ItemCat> queryByPid(Integer id) throws IOException{ /* * 商品分類要使用快取步驟: * 1)先判斷快取中是否有資料,如果有資料就讀取,直接返回 * 2)如果快取中沒有資料,要繼續執行業務,不能丟擲異常 * 3)執行完業務,要多一步動作,要把結果放入快取中string,先把java物件轉換成json串,kv寫入快取中。 */ MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); String ITEM_CAT_KEY = "ITEM_CAT_" + id; //唯一性 //從redis中獲取資料 String jsonItemCat = redisService.get(ITEM_CAT_KEY); if(StringUtils.isNotEmpty(jsonItemCat)){ JsonNode jsonNode = MAPPER.readTree(jsonItemCat); //把json串轉換JsonNode //利用jackson提供方法,將json串轉成java物件,List<Object> List<ItemCat> itemCatList = MAPPER.readValue(jsonNode.traverse(), MAPPER.getTypeFactory().constructCollectionType(List.class, ItemCat.class)); return itemCatList; }else{ //繼續執行業務,一般都是去資料庫訪問 List<ItemCat> itemCatList = itemCatMapper.queryByPid(id); //寫redis,kv(string,string) jsonItemCat = MAPPER.writeValueAsString(itemCatList); //將java物件轉成json串 redisService.set(ITEM_CAT_KEY, jsonItemCat); return itemCatList; } } }
Redis主從複製
主從複製
cp redis.conf redis-master.conf #主節點配置 redis-server redis-master.conf #啟動主 cp redis.conf redis-slave01.conf #從1配置,修改埠 6380 redis-server redis-slave01.conf #啟動從1 redis-cli –p 6380 #登入從1 slaveof 127.0.0.1 6379 #掛接到主 cp redis.conf redis-slave02.conf #從2配置,修改埠6381 redis-server redis-slave02.conf #啟動從2 redis-cli –p 6381 #登入從2 slaveof 127.0.0.1 6379 #掛接到主
檢查配置
info #檢視所有資訊
info Replication #只檢視Replication片段資訊
檢視結果,確認狀態
127.0.0.1:6379> info Replication # Replication role:master #說明master生效 connected_slaves:2 #master主節點下有兩個從節點 slave0:ip=127.0.0.1,port=6380,state=online,offset=845,lag=0 slave1:ip=127.0.0.1,port=6381,state=online,offset=845,lag=1 master_repl_offset:845 repl_backlog_active:1 repl_backlog_size:1048576 repl_backlog_first_byte_offset:2 repl_backlog_histlen:844 127.0.0.1:6379>
測試
127.0.0.1:6379>set name tony
127.0.0.1:6380>get name #讀取到同步的資訊
127.0.0.1:6381>get name
127.0.0.1:6381>set name hellen #報錯,從上不允許設定資料
(error) READONLY You can't write against a read only slave.
Redis哨兵實現HA高可用
哨兵實現實時冗餘備份和容災,但不支援分片。
哨兵sentinel
Redis Sentinel(哨兵)是一個分散式系統,你可以在一個架構中執行多個 Sentinel 程序(progress), 這些程序使用流言協議(gossip protocols)來接收關於主伺服器是否下線的資訊,並使用投票協議(agreement protocols)來決定是否執行自動故障遷移,以及選擇哪個從伺服器作為新的主伺服器。
Sentinel系統用於管理多個Redis伺服器(instance),該系統執行以下三個任務:
- 監控(Monitoring): Sentinel 會不斷地檢查你的主伺服器和從伺服器是否運作正常。
- 提醒(Notification): 當被監控的某個 Redis 伺服器出現問題時,Sentinel 可以通過 API 向管理員或者其他應用程式傳送通知。
- 自動故障遷移(Automatic failover):當一個主伺服器不能正常工作時, Sentinel 會開始一次自動故障遷移操作,它會將失效主伺服器的其中一個從伺服器升級為新的主伺服器,並讓失效主伺服器的其他從伺服器改為複製新的主伺服器; 當客戶端試圖連線失效的主伺服器時,叢集也會向客戶端返回新主伺服器的地址, 使得叢集可以使用新主伺服器代替失效伺服器。
哨兵的工作原理
sentinel以每10秒一次的頻率向master傳送info命令,通過info的回覆來分析master資訊,master的回覆主要包含了兩部分資訊,一部分是master自身的資訊,一部分是master所有的slave(從)的資訊,所以sentinel可以自動發現master的從服務。sentinel從master獲取到的master自身資訊以及master所有的從資訊,將會更新到sentinel的sentinelState中及masters(sentinelRedisInstance結構)中的slaves字典中。
哨兵sentinel-實現高可用
哨兵sentinel類似zookeeper。它含有監控,監控每個節點的活躍狀態。
上面配置了3個節點,但如果主宕機,整個快取系統就癱瘓,如何實現主宕機,自動從多個從中選舉出一個節點當主呢?redis在3.0版本之後提供了哨兵sentinel。通過哨兵實現高可用。
但一個哨兵也可能宕機,一次啟動兩個哨兵,自身也實現高可用。
cp sentinel.conf sentinel2.conf #複製哨兵
26379為26380 #修改埠
sentinel monitor mymaster 192.168.163.20 6379 1 #設定訪問名稱
#最後的數值為選舉時過票數量(坑)
redis-sentinel sentinel.conf #啟動哨兵
redis-sentinel sentinel2.conf #啟動哨兵2,形成哨兵的高可用
ps –ef|grep redis #檢視程序
6010 5709 0 00:38 pts/2 00:00:13 redis-server 127.0.0.1:6379
6012 5710 0 00:38 pts/2 00:00:13 redis-server 127.0.0.1:6380
6014 5721 0 00:38 pts/3 00:00:13 redis-server 127.0.0.1:6381
6018 5927 1 00:39 pts/6 00:00:21 redis-server *:26379 [sentinel]
6047 6037 1 00:41 pts/7 00:00:19 redis-server *:26380 [sentinel]
6241 2512 0 01:10 pts/1 00:00:00 grep redis
測試
kill 6010 #可以看到slave的兩個節點開始報連結拒絕錯誤,不一會哨兵將6380切換為主
info #在6380上info命令,可以看到其role:master
kill 6018 #刪除一個哨兵,在6380上set資料,6381自動同步
sentinel的坑
開放埠或者關閉防火牆
6379,6380,6381
26379,26380
service iptables stop
protected-mode
預設情況下,Redis node和sentinel的protected-mode都是yes,在搭建叢集時,若想從遠端連線redis叢集,需要將redis node和sentinel的protected-mode修改為no,若只修改redis node,從遠端連線sentinel後,依然是無法正常使用的,且sentinel的配置檔案中沒有protected-mode配置項,需要手工新增。
遠端訪問拒絕
sentinel.conf預設配置
sentinel monitor mymaster 127.0.0.1 6380 1
當redis和sentinel在一臺伺服器上時,必須指定實際的IP地址
sentinel monitor mymaster 192.168.163.30 6380 1
選舉數
sentinel.conf中96行左右的位置
sentinel monitor mymaster 127.0.0.1 6379 2
最後的2代表選舉的個數,這個值非常關鍵。其中的2表示只有在兩個sential程序發現master不可用時才執行failover故障轉移。例如:即使一個master宕機,如果投票個數未超過1個,redis不會觸發failover,不會觸發選舉,而是一直等待master恢復,當master恢復,一切又工作正常。只有當投票數大於等於1時,才認為master才會觸發選舉,自動從眾多的slave中選擇一個節點升級為master,其他自動從節點自動連線次節點。同時會自動修改sentinel.conf檔案
sentinel monitor mymaster 192.168.163.30 6380 1
預設30秒進行切換
修改從節點的選舉優先順序
redis.conf
slave-priority 100
這樣當Master掛掉的時候Sentinel會優先選擇slave-priority值較小的作為新的Master。
sentinel.conf配置詳解
配置語句 |
說明 |
daemonize yes |
以後臺程序模式執行 |
port 26379 |
哨兵的埠號,該埠號預設為26379,不得與任何redis node的埠號重複 |
logfile " /var/log/redis/sentinel.log " |
log檔案所在地 |
sentinel monitor master1 192.168.163.30 6379 1 |
(第一次配置時)哨兵對哪個master進行監測,此處的master1為一“別名”可以任意,將來程式訪問時使用,如sentinel-26379。然後哨兵會通過這個別名後的IP知道整個該master內的slave關係。因此你不用在此配置slave是什麼而由哨兵自己去維護這個“連結串列”。 |
sentinel monitor master1 192.168.163.30 6379 1 |
最後一個1代表當節點宕機時的觸發選舉的判斷條件,1就代表sentinel認定宕機的個數,必須大於這個個數,選舉才開始發生,預設值為2,很坑。 |
sentinel down-after-milliseconds master1 1000 |
如果master在多少秒內無反應哨兵會開始進行master-slave間的切換,使用“選舉”機制 |
sentinel failover-timeout master1 5000 |
如果在多少秒內沒有把宕掉的那臺master恢復,那哨兵認為這是一次真正的宕機,而排除該宕掉的master作為節點選取時可用的node然後等待一定的設定值的毫秒數後再來探測該節點是否恢復,如果恢復就把它作為一臺slave加入哨兵監測節點群並在下一次切換時為他分配一個“選取號”。 |
安全訪問
redis.conf
masterauth "123456"
requirepass "123456"
sentinel.conf
sentinel auth-pass mymaster 123456
否則在每個的redis-cli中執行語句:
CONFIG SET protected-mode no
jedis訪問時
jedis.auth("123456");
jedis訪問sentinel
@Test
public void sentinel(){
Set<String> sentinels = new HashSet<String>();
sentinels.add(new HostAndPort("192.168.163.30",26379).toString());
//sentinels.add(new HostAndPort("192.168.163.30",26380).toString());
//mymaster是在sentinel.conf中配置的名稱
//sentinel monitor mymaster 192.168.163.30 6380 1
JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels);
System.out.println("當前master:" + pool.getCurrentHostMaster());
Jedis jedis = pool.getResource();
//jedis.auth("123456");
System.out.println(jedis.get("num"));
pool.returnResource(jedis);
pool.destroy();
System.out.println("ok");
}