1. 程式人生 > >億級併發|day10-Redis進階

億級併發|day10-Redis進階

1 Redis持久化策略

1.1 策略說明

說明: redis作為記憶體資料庫,需要保持大量使用者的資料。但是redis中的資料儲存在記憶體中,一旦遇上斷電/宕機,肯定會導致記憶體資料丟失。 所以為了防止資料丟失,redis採用持久化的方式,實現記憶體資料的備份。

策略說明: 當redis記憶體中有資料時,自身支援兩種策略模式:

  • RDB模式
  • AOF模式

redis根據相應模式的設定進行資料持久化,且RDB模式和AOF模式都有各自的持久化檔案。當redis重啟時,redis會根據配置檔案中指定的持久化檔名稱,載入持久化檔案,為記憶體恢復資料。

1.2 RDB模式

1.2.1 模式說明

RDB模式定期

將記憶體中的資料持久化。 如果使用者允許丟失少量的資料則首選RDB模式,因為RDB模式定期為記憶體做快照,該方式的備份速度很快。

1.2.2 備份命令

**說明:**執行redis備份命令需要在redis客戶端執行。

命令: 手動儲存

save

後臺備份

bgsave

區別: save 會造成執行緒阻塞,只有當備份完成時,才允許執行redis更新操作。 bgsave 表示後臺執行,不會造成執行緒阻塞,挑當前不忙的時間做資料備份。

在這裡插入圖片描述

1.2.3 備份方式

save 900 1

在900秒內,redis做一次更新操作,則備份一次

save 300 10

在300秒內,redis做10次更新操作,則備份一次

save 60 10000

在60秒內,如果redis做10000次操作則備份一次

1.2.4 配置檔案說明

1.持久化檔名稱 在這裡插入圖片描述

2.持久化檔案儲存路徑

dir ./

表示當前資料夾,建議使用絕對路徑。

1.3 AOF模式

1.3.1 模式說明

AOF模式可以做到實時資料備份,該模式相當於用配置檔案記錄了使用者的全部操作過程。

特點:

  • 可以實時備份資料,安全性好
  • 持久化速度較RDB模式更慢
  • AOF模式的持久化檔案的體積會很大
  • 當資料恢復時,需要消耗很長時間
  • 持久化檔案明文儲存,沒有加密

1.3.2 AOF模式持久化策略

1.開啟AOF模式 注意:開啟AOF模式後,RDB模式不生效。 在這裡插入圖片描述

2.AOF模式持久化檔案儲存路徑

dir ./

3.持久化策略

# appendfsync always    每次操作都會備份
appendfsync everysec    每秒備份一次
# appendfsync no         不做操作

2 Redis記憶體策略

2.1 需求分析

question: 為了保證伺服器正常執行,需要為redis設定最大記憶體空間,但是如果資料一直新增,記憶體很快就會佔滿,如何優化記憶體?

解決方案: 採用LRU演算法,將記憶體中最近最不常用的資料清空,儲存其他資料。

2.2 記憶體優化手段

1.設定記憶體空間 建議記憶體不要超過1G,通常256~512M足矣。

修改redis配置檔案第537行 在這裡插入圖片描述

2.設定合適的記憶體策略 可選的記憶體策略:

  • volatile-lru 在已經設定超時時間的資料中,採用LRU演算法進行刪除。

  • allkeys-lru 在所有key中,採用LRU演算法進行刪除。

  • volatile-random 在已經設定超時時間的資料中,隨機刪除。

  • allkeys-radom 在所有key中,隨機刪除

  • volatile-ttl 在已經設定超時時間的資料中,根據TTL機制排序,將馬上要過期的資料刪除。

  • noviction 如果採用該機制,那麼記憶體資料不會刪除,將報錯訊息返回給使用者。

策略設定: 在這裡插入圖片描述

2.3 快取使用問題

1.快取穿透

條件:訪問一條不存在的資料

說明:當訪問一個不存在的資料時,因為快取中沒有這個key,導致快取形同虛設,最終訪問後臺資料庫,但資料庫中也沒有該資料所以返回null。

隱患:如果有人惡意頻繁查詢一個不存在的資料,可能會導致資料庫負載過高而宕機。

總結:業務系統訪問一個不存在的資料,稱之為快取穿透。

防護:限定同一IP訪問頻率,如京東。

2.快取擊穿

條件:當一條快取失效/過期/未命中時,高併發訪問該key

說明:如果給一個key設定了失效時間,當key失效時有一萬的併發請求訪問這個key,此時快取失效,所有的請求都會訪問後臺資料庫,稱之為快取擊穿。

場景:微博熱點訊息訪問量很大,如果該快取失效則會直接訪問後臺資料庫,導致後臺資料庫負載過高。

3.快取雪崩

前提:高併發訪問,快取命中較低或者失效時。

說明:假設快取都設定了失效時間,在同一時間內快取大量失效,如果這時使用者高併發訪問,快取命中率過低,導致全部的使用者訪問都會訪問後臺真實的資料庫。

場景:在高併發情況下,快取動態更新時。

3 Redis分片技術

3.1 需求分析

1.如果將全部資料都儲存到一臺tomcat中,如果該伺服器損壞,則將影響全部服務。 2.使用單臺redis記憶體設定一般不要超過1G,但有些業務資料量很大,如果不修改記憶體則無法儲存。

3.2 改進方案

方案:採用Redis分片技術實現。

優點:

  • 使用redis分片可以實現記憶體資料的動態擴容。
  • 使用分片,每臺redis節點中儘可能存放1/n的資料,防止資料丟失。
  • 對於使用者而言,整個redis分片就是一個服務。

3.3 分片搭建

3.3.1 複製配置檔案

說明:將redis.conf檔案複製到shards中,並且複製3份名稱為:

  • redis-6379.conf
  • redis-6380.conf
  • redis-6381.conf

在這裡插入圖片描述

3.3.2 修改埠號

說明:分別修改6380/6381的配置檔案為對應埠 在這裡插入圖片描述

3.3.3 重啟Redis服務

在這裡插入圖片描述

3.3.4 分片測試

@Test
public void testShard(){

	/**
	 * 建立分片的物件
	 * 1.poolConfig  標識池的大小
	 * 2.shards redis分片的節點資訊
	 */
	
	JedisPoolConfig poolConfig = new JedisPoolConfig();
	poolConfig.setMaxTotal(1000);
	poolConfig.setTestOnBorrow(true); //獲取連結時先檢測
	
	List<JedisShardInfo> shards = new ArrayList<>();
	shards.add(new JedisShardInfo("192.168.126.166",6379));
	shards.add(new JedisShardInfo("192.168.126.166",6380));
	shards.add(new JedisShardInfo("192.168.126.166",6381));
	
	ShardedJedisPool pool = 
	new ShardedJedisPool(poolConfig, shards);
	
	//獲取redis連結
	ShardedJedis jedis = pool.getResource();
	
	jedis.set("shards","儲存分片資料");
	System.out.println(jedis.get("shards"));
	//將連結還回池中
	pool.returnResource(jedis);
}

3.4 Hash一致性演算法

3.4.1 資料如何儲存

在這裡插入圖片描述

1.利用節點的IP+演算法確定唯一的雜湊值,之後在記憶體中確定節點的位置。 2.當儲存資料時,根據key進行hash運算,確定唯一的一個位置。 3.根據當前key位置順時針查詢最近的node節點進行掛載。

3.4.2 均衡性

說明:根據redis節點的數量儘可能讓資料均勻地分片,每個節點中的資料儘可能趨向1/n。

提升:為了保證均衡性,雜湊一致性演算法引入了虛擬節點的概念。為了平衡資料,如果一個節點不夠則生成多個節點。 在這裡插入圖片描述

3.4.3 單調性

說明:如果node節點的新增,能動態地實現資料的遷移,這種特性被稱之為單調性。 在這裡插入圖片描述

3.4.4 分散性

特點:由於分散式的原因,使用者在使用記憶體時,不能夠獲取全部的記憶體空間,導致一個key對應多個位置。 在這裡插入圖片描述

3.4.5 負載

說明:負載是從另一個角度考慮分散性。

特點:一個位置對應多個key 在這裡插入圖片描述

如何解決:在進行架構設計時,要求使用全部的記憶體空間。

4 Spring整合分片

4.1 編輯pro檔案

redis.host=192.168.126.166
redis.port.a=6379
redis.port.b=6380
redis.port.c=6381
redis.maxTotal=1000

4.2 編輯Spring配置檔案

<!--實現spring整合分片  -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
	<property name="maxTotal" value="${redis.maxTotal}"/>
</bean>

<!--定義三個redis節點  -->
<bean id="shardInfoA" class="redis.clients.jedis.JedisShardInfo">
	<constructor-arg name="host" value="${redis.host}"/>
	<constructor-arg name="port" value="${redis.port.a}"/>
</bean>

<bean id="shardInfoB" class="redis.clients.jedis.JedisShardInfo">
	<constructor-arg name="host" value="${redis.host}"/>
	<constructor-arg name="port" value="${redis.port.b}"/>
</bean>

<bean id="shardInfoC" class="redis.clients.jedis.JedisShardInfo">
	<constructor-arg name="host" value="${redis.host}"/>
	<constructor-arg name="port" value="${redis.port.c}"/>
</bean>

<!--定義連線池  -->
<bean id="jedisPool" class="redis.clients.jedis.ShardedJedisPool">
	<constructor-arg name="poolConfig" ref="poolConfig"/>
	<constructor-arg name="shards">
		<list>
			<ref bean="shardInfoA"/>
			<ref bean="shardInfoB"/>
			<ref bean="shardInfoC"/>
		</list>
	</constructor-arg>
</bean>

4.3 編輯工具API

@Service
public class RedisService {

	//有的工程需要,有的工程不需要。設定required=false,有就注入,沒有就不注入。
    @Autowired(required = false)
    private ShardedJedisPool shardedJedisPool;

    
    public void set(String key,String value){
    	ShardedJedis jedis = 
    			shardedJedisPool.getResource();
    	
    	jedis.set(key, value);
    	shardedJedisPool.returnResource(jedis);
    }
    
    //新增超時時間
    public void set(String key,String value,int seconds){
    	ShardedJedis jedis = 
    			shardedJedisPool.getResource();
    	
    	jedis.setex(key, seconds, value);
    	shardedJedisPool.returnResource(jedis);
    }
    
    //編輯get方法
    public String get(String key){
    	ShardedJedis jedis = 
    			shardedJedisPool.getResource();
    	String result = jedis.get(key);
    	shardedJedisPool.returnResource(jedis);
    	return result;
    }
}

4.4 編輯業務層方法

1.修改自動注入物件 在這裡插入圖片描述

2.切換業務方法 在這裡插入圖片描述

5 Redis哨兵

5.1 業務需求

採用redis分片技術可以實現記憶體擴容,但是如果其中一臺機器宕機,則整個redis分片將不能正常執行。

5.2 實現主從掛載

角色劃分: 6379(主機) 6380(從機) 6381(從機)

1.檢查節點狀態 命令:

info replication

在這裡插入圖片描述

2.實現主從掛載 命令:

127.0.0.1:6380> SLAVEOF 192.168.126.166 6379

3.檢查狀態 在這裡插入圖片描述

5.3 哨兵實現

5.3.1 哨兵原理

在這裡插入圖片描述

  • 哨兵監控主機的狀態,並獲取主機的全部資訊,包括從機的資訊。
  • 通過心跳檢測機制,如果3次連線沒有響應,則斷定主機宕機了。此時哨兵會從從機中選舉一臺從機充當從機,同時將另外的從機掛載到現在的主機。
  • 當舊的主機修復完成後,繼續充當從機,等待下次選舉。

5.3.2 編輯哨兵配置檔案

1.以原名儲存檔案

cp sentinel.conf sentinel

2.關閉保護模式 在這裡插入圖片描述

3.修改哨兵監聽節點資訊

sentinel master mymaster 127.0.0.1 1

說明: mymaster 表示主機變數名稱 IP:埠 表示主機資訊 2 表示選舉票數 在這裡插入圖片描述

4.修改推選時間 在這裡插入圖片描述

5.修改推選失敗時間 在這裡插入圖片描述

5.3.3 哨兵測試

1.啟動哨兵

redis-sentinel sentinel.conf

2.啟動測試 在這裡插入圖片描述

3.關閉主機,檢查哨兵能否推選 在這裡插入圖片描述