億級流量架構|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.關閉主機,檢查哨兵能否推選
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章