中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

濱州網(wǎng)站建設(shè)phpi百度網(wǎng)盤帳號登錄入口

濱州網(wǎng)站建設(shè)phpi,百度網(wǎng)盤帳號登錄入口,怎樣知道網(wǎng)站有沒有做推廣,django做的網(wǎng)站舉例文章目錄一、緩存更新策略1、三種策略2、策略選擇3、主動更新的方案二、緩存存在的問題1、緩存穿透2、緩存雪崩3、緩存擊穿三、解決緩存問題1、自定義分布式鎖2、解決緩存穿透問題3、解決緩存擊穿問題一、緩存更新策略 1、三種策略 內(nèi)存淘汰:redis自帶的內(nèi)存淘汰機…

文章目錄

    • 一、緩存更新策略
      • 1、三種策略
      • 2、策略選擇
      • 3、主動更新的方案
    • 二、緩存存在的問題
      • 1、緩存穿透
      • 2、緩存雪崩
      • 3、緩存擊穿
    • 三、解決緩存問題
      • 1、自定義分布式鎖
      • 2、解決緩存穿透問題
      • 3、解決緩存擊穿問題

一、緩存更新策略

1、三種策略

  • 內(nèi)存淘汰:redis自帶的內(nèi)存淘汰機制
  • 過期淘汰:利用expire命令給數(shù)據(jù)設(shè)置過期時間
  • 主動更新:主動完成數(shù)據(jù)庫和緩存的同時更新

2、策略選擇

  • 低一致性需求:內(nèi)存淘汰或過期淘汰
  • 高一致性需求:主動更新為主,過期淘汰兜底

3、主動更新的方案

  • Cache Aside:緩存調(diào)用者在更新數(shù)據(jù)庫的同時完成對緩存的更新
    • 一致性良好
    • 實現(xiàn)難度一般
  • Read/Write Through:緩存與數(shù)據(jù)庫成為一個服務(wù),服務(wù)保證兩者的一致性,對外暴露的API接口。調(diào)用者調(diào)用API,無需知道自己操作的數(shù)據(jù)庫還是緩存,不關(guān)心一致性
    • 一致性優(yōu)秀
    • 實現(xiàn)復(fù)雜
    • 性能一般
  • Write Back:緩存調(diào)用者的CRUD都針對緩存完成。由獨立線程異步的將緩存寫到數(shù)據(jù)庫,實現(xiàn)最終一致
    • 一致性差
    • 性能好
    • 實現(xiàn)復(fù)雜

二、緩存存在的問題

1、緩存穿透

產(chǎn)生原因:客戶端請求的數(shù)據(jù)在緩存和數(shù)據(jù)庫中都不存在。當(dāng)這種情況大量出現(xiàn)或被惡意攻擊時,接口的訪問全部透過Redis訪問數(shù)據(jù)庫,而數(shù)據(jù)庫中也沒有這些數(shù)據(jù),我們稱這種現(xiàn)象為"緩存穿透"。

解決方案:

  1. 緩存空對象:對于不存在的數(shù)據(jù)也在Redis建立緩存,值為空,設(shè)置一個較短的TTL時間
    • 優(yōu)點:實現(xiàn)簡單,維護方便
    • 缺點:額外消耗內(nèi)存,短期的數(shù)據(jù)不一致
  2. 布隆過濾:利用布隆過濾算法,在請求Redis之前先判斷是否存在,如果不存在則直接拒絕訪問
    • 優(yōu)點:內(nèi)存占用少
    • 缺點:實現(xiàn)復(fù)雜,存在誤判的可能性
  3. 其他方法:
    1. 做好數(shù)據(jù)的基礎(chǔ)格式校驗
    2. 加強用戶權(quán)限校驗
    3. 做好熱點數(shù)據(jù)的限流

布隆過濾器:

一種數(shù)據(jù)結(jié)構(gòu),由一串很長的二進制向量組成,可以將其看成一個二進制數(shù)組。

當(dāng)要向布隆過濾器中添加一個元素key時,我們通過多個hash函數(shù),算出一個值,然后將這個值所在的方格置為1。

因為多個不同的數(shù)據(jù)通過hash函數(shù)算出來的結(jié)果是會有重復(fù)的,所以布隆過濾器可以判斷某個數(shù)據(jù)一定不存在,但是無法判斷一定存在。

優(yōu)點:優(yōu)點很明顯,二進制組成的數(shù)組,占用內(nèi)存極少,并且插入和查詢速度都足夠快。

缺點:隨著數(shù)據(jù)的增加,誤判率會增加;還有無法判斷數(shù)據(jù)一定存在;另外還有一個重要缺點,無法刪除數(shù)據(jù)。

2、緩存雪崩

產(chǎn)生原因:在同一時間段大量的緩存key同時失效或者Redis服務(wù)宕機,導(dǎo)致大量請求到達數(shù)據(jù)庫,帶來巨大壓力

解決方案:

  1. 給不同的Key的TTL設(shè)置隨機值
  2. 利用Redis集群提高服務(wù)的可用性
  3. 誒緩存業(yè)務(wù)添加降級限流策略
  4. 給業(yè)務(wù)添加多級緩存

3、緩存擊穿

產(chǎn)生原因:熱點Key在某一個時間段被高并發(fā)訪問,而此時Key正好過期,如果重建緩存時間耗時長,在這段時間內(nèi)大量請求剾數(shù)據(jù)庫,帶來巨大沖擊

解決方案:

  1. 設(shè)置value永不過期:通過定時任務(wù)進行數(shù)據(jù)庫查詢更新緩存,當(dāng)然前提時不會給數(shù)據(jù)庫造成壓力過大
    • 優(yōu)點:最可靠,性能好
    • 缺點:占空間,內(nèi)存消耗大,一致性差
  2. 互斥鎖:給緩存重建過程加鎖,確保重建過程只有一個線程執(zhí)行,其他線程等待
    • 優(yōu)點:實現(xiàn)簡單,沒有額外內(nèi)存消耗,一致性好
    • 缺點:等待導(dǎo)致性能下降,有死鎖風(fēng)險
  3. 邏輯過期:熱點Key緩存永不過期,認識設(shè)置一個邏輯過期時間,查詢到數(shù)據(jù)時通過對邏輯時間判斷,來決定是否需要進行緩存重建。重建過程也通過互斥鎖來保證單線程執(zhí)行。利用獨立線程異步執(zhí)行,其他線程無需等待,直接查詢到舊的數(shù)據(jù)即可。
    • 優(yōu)點:線程無需等待,性能較好
    • 缺點:不保證一致性,有額外內(nèi)存消耗,實現(xiàn)復(fù)雜
private final RedisTemplate<String, String> redisTemplate;private static final ExecutorService CACHE_REBUILD_EXECUTOR = new ThreadPoolExecutor(10, 10, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(20), r -> new Thread(r, "cache_rebuild"));public CacheClient(RedisTemplate<String, String> redisTemplate) {this.redisTemplate = redisTemplate;
}public void setWithLogicalExpire(String key, Object value, Long expireTime, TimeUnit unit) {// 設(shè)置邏輯過期時間RedisData redisData = new RedisData();redisData.setValue(value);redisData.setExpireTime(LocalDateTime.now().plusNanos(unit.toNanos(expireTime)));redisTemplate.opsForValue().set(key, JSON.toJSONString(redisData));
}/*** 邏輯過期,互斥鎖獲取值,用于避免熱點數(shù)據(jù)出現(xiàn)緩存擊穿*/
public <R, V> R getMutex(String keyPrefix, V id, Class<R> clazz, Function<V, R> dbFallback, Long expireTime, TimeUnit unit) {String key = keyPrefix + id;String value = redisTemplate.opsForValue().get(key);if (StringUtils.isBlank(value)) {return null;}RedisData redisData = JSON.parseObject(value, RedisData.class);R result = JSONUtil.toBean((JSONObject) redisData.getValue(), clazz);if (redisData.getExpireTime().isAfter(LocalDateTime.now())) {return result;}// 如果緩存已過期,則嘗試更新String localKey = RedisConstant.LOCK + id;// 獲取鎖成功if (getLock(localKey)) {// 異步更新緩存CACHE_REBUILD_EXECUTOR.submit(() -> {try {R res = dbFallback.apply(id);this.setWithLogicalExpire(key, res, expireTime, unit);} catch (Exception e) {throw new RuntimeException(e);} finally {unLock(localKey);}});}return result;
}private boolean getLock(String key) {// 直接返回會進行自動拆箱,可能會出現(xiàn)空指針異常return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(key, "1"));
}private void unLock(String key) {redisTemplate.delete(key);
}

三、解決緩存問題

1、自定義分布式鎖

/*** <pre>* 簡易實現(xiàn)的Redis分布式鎖* </pre>** @author <a href="https://github.com/Ken-Chy129">Ken-Chy129</a>* @date 2023/2/26 21:18*/
public class SimpleRedisLock {private final RedisTemplate<String, String> redisTemplate;/**鎖的名字,根據(jù)業(yè)務(wù)設(shè)置*/private final String lockName;/*** key前綴*/private static final String KEY_PREFIX = "lock:";/*** value中線程標(biāo)識的前綴(為每個節(jié)點提供一個隨機的前綴,避免集群部署下線程id出現(xiàn)重復(fù)而導(dǎo)致value出現(xiàn)相同的情況)*/private static final String ID_PREFIX = UUID.fastUUID().toString(true);/*** 釋放鎖邏輯的lua腳本*/private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;static {UNLOCK_SCRIPT = new DefaultRedisScript<>();UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));UNLOCK_SCRIPT.setResultType(Long.class);}public SimpleRedisLock(String lockName, RedisTemplate<String, String> redisTemplate) {this.lockName = lockName;this.redisTemplate = redisTemplate;}public boolean tryLock(long timeoutSec) {long threadId = Thread.currentThread().getId();// 返回的是Boolean類型,直接return會進行自動拆箱,可能會出現(xiàn)空指針異常// 需要為鎖設(shè)置過期時間,防止因服務(wù)宕機而導(dǎo)致鎖無法釋放return Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + lockName, ID_PREFIX + threadId, timeoutSec, TimeUnit.SECONDS));}public void unlock() {redisTemplate.execute(UNLOCK_SCRIPT,Collections.singletonList(KEY_PREFIX + lockName),ID_PREFIX + Thread.currentThread().getId());}
}

Lua腳本——unlock.lua

--- 比較線程標(biāo)識與鎖中的標(biāo)識是否一致
if(redis.call('get', KEYS[1]) == ARGS[1]) then--- 釋放鎖return redis.call('del', KEYS[1])
end
return 0

使得釋放鎖的操作具有原子性

Redis是單線程處理,本身不會存在并發(fā)問題,但是由于可能有多個客戶端訪問,每個客戶端會有一個線程,之間存在競爭,所以服務(wù)端收到的指令有可能出現(xiàn)多個客戶端的指令穿插,而lua腳本可以保證多條指令的原子性從而解決并發(fā)問題

2、解決緩存穿透問題

/*** 避免緩存穿透的獲取*/
public <R, V> R get(String keyPrefix, V id, Class<R> clazz, Function<V, R> dbFallback, Long expireTime, TimeUnit unit) {String key = keyPrefix + id;// 查詢緩存String value = redisTemplate.opsForValue().get(key);// 緩存存在則直接返回if (StringUtils.isNotBlank(value)) {return JSON.parseObject(value, clazz);}// 緩存不存在(到此處說明value要么是空,要么是null)if (value != null) {// 不為null則說明為“”,代表數(shù)據(jù)不存在,直接返回null,不用查詢數(shù)據(jù)庫(解決緩存穿透問題)return null;}// value為null則查詢數(shù)據(jù)庫獲取數(shù)據(jù)進行更新R result = dbFallback.apply(id);if (result == null) {// 數(shù)據(jù)庫查詢不到結(jié)果,則存入空串避免緩存穿透redisTemplate.opsForValue().set(key, "", RedisConstant.CACHE_NULL_TTL, TimeUnit.MINUTES);return null;}// 查詢到結(jié)果,寫回緩存this.set(key, result, expireTime, unit);return result;
}

3、解決緩存擊穿問題

/*** 邏輯過期,互斥鎖獲取值,用于避免熱點數(shù)據(jù)出現(xiàn)緩存擊穿*/
public <R, V> R getMutex(String keyPrefix, V id, Class<R> clazz, Function<V, R> dbFallback, Long expireTime, TimeUnit unit) {String key = keyPrefix + id;String value = redisTemplate.opsForValue().get(key);if (StringUtils.isBlank(value)) {return null;}RedisData redisData = JSON.parseObject(value, RedisData.class);R result = JSONUtil.toBean((JSONObject) redisData.getValue(), clazz);if (redisData.getExpireTime().isAfter(LocalDateTime.now())) {return result;}// 如果緩存已過期,則獲取鎖嘗試更新SimpleRedisLock lock = new SimpleRedisLock(key, redisTemplate);// 獲取鎖成功if (lock.tryLock(5)) {// 異步更新緩存CACHE_REBUILD_EXECUTOR.submit(() -> {try {R res = dbFallback.apply(id);this.setWithLogicalExpire(key, res, expireTime, unit);} catch (Exception e) {throw new RuntimeException(e);} finally {lock.unlock();}});}return result;
}
http://www.risenshineclean.com/news/43075.html

相關(guān)文章:

  • 楊莊網(wǎng)站建設(shè)廣告推廣渠道有哪些
  • 龍崗企業(yè)網(wǎng)站制作公司資源
  • 微信公眾平臺官方網(wǎng)谷歌網(wǎng)站推廣優(yōu)化
  • 網(wǎng)站怎樣做自適應(yīng)分辨率大小公司網(wǎng)絡(luò)推廣該怎么做
  • laravel 做網(wǎng)站宣傳軟文
  • 微商水印相機做網(wǎng)站cps推廣平臺
  • 區(qū)塊鏈開發(fā)技術(shù)的應(yīng)用做神馬seo快速排名軟件
  • 太原網(wǎng)站建設(shè)制作寧波seo優(yōu)化定制
  • 優(yōu)酷專門給馬天宇做的網(wǎng)站優(yōu)化大師下載安裝app
  • 東莞seo建站如何推廣長沙服務(wù)好的網(wǎng)絡(luò)營銷
  • 數(shù)商云價格江西seo推廣
  • virmach搭建wordpress蘇州seo網(wǎng)站推廣哪家好
  • 河北云建站鄭州seo優(yōu)化大師
  • 自己做盜版影視網(wǎng)站如何優(yōu)化培訓(xùn)體系
  • 微信漫畫網(wǎng)站模板百度外推代發(fā)排名
  • 開平做網(wǎng)站百度官方版
  • 賣掉的網(wǎng)站了對方用來做違法短鏈接在線生成免費
  • 各種網(wǎng)站解決方案免費建站建站abc網(wǎng)站
  • go語言做的網(wǎng)站汕頭seo網(wǎng)站建設(shè)
  • 硬件開發(fā)網(wǎng)站輿情分析系統(tǒng)
  • 做網(wǎng)站需要什么百度關(guān)鍵詞推廣價格
  • python網(wǎng)站開發(fā)好嗎東莞seo外包
  • 域名解析網(wǎng)站鄭州網(wǎng)絡(luò)公司
  • 網(wǎng)站備案流程教程seo公司上海牛巨微
  • 網(wǎng)站網(wǎng)頁設(shè)計怎樣百度關(guān)鍵詞指數(shù)
  • 常州網(wǎng)站制作公司多嗎寶雞網(wǎng)站開發(fā)公司
  • 蜜蜂vp加速器七天試用杭州優(yōu)化公司在線留言
  • 環(huán)保業(yè)網(wǎng)站建設(shè)的策劃軟文是指什么
  • 百度網(wǎng)站建設(shè)要多少錢春哥seo博客
  • 容桂銷售型網(wǎng)站建設(shè)知乎關(guān)鍵詞排名