EA官方對《FIFA》引導開箱檔案洩露引發爭議作出迴應
阿新 • • 發佈:2021-04-28
redis
redis 資料型別以及應用場景
- string:驗證碼
- list:訂單列表
- hash:購物車
- set:訂單列表
- Sorted Set:排行榜
redis 持久化方式
- RDB持久化是指在指定的時間間隔內將記憶體中的資料集快照寫入磁碟,實際操作過程是fork一個子程序,先將資料集寫入臨時檔案,寫入成功後,再替換之前的檔案,用二進位制壓縮儲存。
- AOF持久化以日誌的形式記錄伺服器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文字的方式記錄,可以開啟檔案看到詳細的操作記錄。
RDB持久化配置
Redis會將資料集的快照dump到dump.rdb檔案中。此外,我們也可以通過配置檔案來修改Redis伺服器dump快照的頻率,在開啟6379.conf檔案之後,我們搜尋save,可以看到下面的配置資訊:
save 900 1 #在900秒(15分鐘)之後,如果至少有1個key發生變化,則dump記憶體快照。
save 300 10 #在300秒(5分鐘)之後,如果至少有10個key發生變化,則dump記憶體快照。
save 60 10000 #在60秒(1分鐘)之後,如果至少有10000個key發生變化,則dump記憶體快照。
AOF持久化配置
在Redis的配置檔案中存在三種同步方式,它們分別是:
appendfsync always #每次有資料修改發生時都會寫入AOF檔案。
appendfsync everysec #每秒鐘同步一次,該策略為AOF的預設策略。
appendfsync no #從不同步。高效但是資料不會被持久化。
參考資料:點選這裡
redis 記憶體淘汰策略
過期策略
我們set key的時候,都可以給一個expire time,就是過期時間,指定這個key比如說只能存活1個小時,我們自己可以指定快取到期就失效。如果假設你設定一個一批key只能存活1個小時,那麼接下來1小時後,redis是怎麼對這批key進行刪除的?
答案是:定期刪除+惰性刪除
- 所謂定期刪除,指的是redis預設是每隔100ms就隨機抽取一些設定了過期時間的key,檢查其是否過期,如果過期就刪除。注意,這裡可不是每隔100ms就遍歷所有的設定過期時間的key,那樣就是一場效能上的災難。
實際上redis是每隔100ms隨機抽取一些key來檢查和刪除的。
- 但是,定期刪除可能會導致很多過期key到了時間並沒有被刪除掉,所以就得靠惰性刪除了。這就是說,在你獲取某個key的時候,redis會檢查一下
,這個key如果設定了過期時間那麼是否過期了?如果過期了此時就會刪除,不會給你返回任何東西。並不是key到時間就被刪除掉,而是你查詢這個key的時候,redis再懶惰的檢查一下
通過上述兩種手段結合起來,保證過期的key一定會被幹掉。但是實際上這還是有問題的,如果定期刪除漏掉了很多過期key,然後你也沒及時去查,也就沒走惰性刪除,此時會怎麼樣?如果大量過期key堆積在記憶體裡,導致redis記憶體塊耗盡了,怎麼辦?
答案是:走記憶體淘汰機制。
記憶體淘汰機制:
如果redis的記憶體佔用過多的時候,此時會進行記憶體淘汰,有如下一些策略:
- noeviction:當記憶體不足以容納新寫入資料時,新寫入操作會報錯,這個一般沒人用吧
- allkeys-lru:當記憶體不足以容納新寫入資料時,在鍵空間中,移除最近最少使用的key(這個是最常用的)
- allkeys-random:當記憶體不足以容納新寫入資料時,在鍵空間中,隨機移除某個key,這個一般沒人用吧
- volatile-lru:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,移除最近最少使用的key(這個一般不太合適)
- volatile-random:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,隨機移除某個key
- volatile-ttl:當記憶體不足以容納新寫入資料時,在設定了過期時間的鍵空間中,有更早過期時間的key優先移除
redis 快取穿透、擊穿、雪崩問題
- 快取穿透:key對應的資料在資料來源並不存在,每次針對此key的請求從快取獲取不到,請求都會到資料來源,從而可能壓垮資料來源。比如用一個不存在的使用者id獲取使用者資訊,不論快取還是資料庫都沒有,若黑客利用此漏洞進行攻擊可能壓垮資料庫。
- 快取擊穿:key對應的資料存在,但在redis中過期,此時若有大量併發請求過來,這些請求發現快取過期一般都會從後端DB載入資料並回設到快取,這個時候大併發的請求可能會瞬間把後端DB壓垮。
- 快取雪崩:當快取伺服器重啟或者大量快取集中在某一個時間段失效,這樣在失效的時候,也會給後端系統(比如DB)帶來很大壓力。
解決方式:使用setnx,配合雙重鎖的機制程式碼如下:
package com.redis.lock;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* setNx 悲觀鎖 解決雪崩 擊穿 穿透問題
* 事物+監聽 解決秒殺 庫存賣超問題。
*/
@Component
public class RedisLockTest extends Thread {
@Override
public void run() {
try {
setNx();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Autowired
StringRedisTemplate stringRedisTemplate;
public String setNx() throws InterruptedException {
System.out.println(Thread.currentThread().getName()+"開始獲取快取資料");
String key = stringRedisTemplate.opsForValue().get("order");
if (StringUtils.isNotBlank(key)){
System.out.println(Thread.currentThread().getName()+"開始獲取快取資料成功,返回");
return key;
}
System.out.println(Thread.currentThread().getName()+"獲取快取資料失敗");
Boolean aBoolean = stringRedisTemplate.opsForValue().setIfAbsent("lock", "1");
if (aBoolean){
System.out.println(Thread.currentThread().getName()+"拿到鎖成功,重新設定快取");
stringRedisTemplate.expire("lock",1, TimeUnit.MINUTES);
//處理業務邏輯
key = stringRedisTemplate.opsForValue().get("order");
if (StringUtils.isNotBlank(key)){
System.out.println(Thread.currentThread().getName()+"---------返回快取資料");
stringRedisTemplate.delete("lock");
return stringRedisTemplate.opsForValue().get("order");
}
//模擬查詢資料庫
Thread.sleep(2000);
stringRedisTemplate.opsForValue().set("order","訂單號為123456");
stringRedisTemplate.delete("lock");
System.out.println(Thread.currentThread().getName()+"。。。。。。返回快取資料");
return stringRedisTemplate.opsForValue().get("order");
}else {
Thread.sleep(500);
setNx();
}
return null;
}
}
redis 叢集模式,以及cluster叢集
參考資料:點選這裡
redis 應用場景
- 登入鎖定
- 驗證碼生成
- springSecurity token
- 分散式事務
- 限流令牌桶
Redis哨兵怎麼實現的-主節點掛掉後從節點怎麼實現轉為主節點的
參考資料 : 點選這裡
redis 叢集的三種模式優缺點
參考資料:點選這裡