從零開始手寫redis(18)緩存淘汰算法 FIFO 優化

項目簡介

大家好,我是老馬。

Cache 用于實現一個可拓展的高性能本地緩存。

有人的地方,就有江湖。有高性能的地方,就有 cache。

v1.0.0 版本

以前的 FIFO 實現比較簡單,但是 queue 循環一遍刪除的話,性能實在是太差。

于是想到引入一個 Set 存儲有哪些 key,改成下面的方式:

package com.github.houbb.cache.core.support.evict.impl;import com.github.houbb.cache.api.ICacheContext;
import com.github.houbb.cache.core.model.CacheEntry;
import com.github.houbb.cache.core.support.evict.AbstractCacheEvict;import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;/*** 丟棄策略-先進先出* @author binbin.hou* @since 0.0.2*/
public class CacheEvictFifo<K,V> extends AbstractCacheEvict<K,V> {/*** queue 信息* @since 0.0.2*/private final Queue<K> queue = new LinkedList<>();/*** 避免數據重復加入問題* @since 1.0.1*/private final Set<K> keySet = new HashSet<>();@Overridepublic CacheEntry<K,V> doEvict(ICacheContext<K, V> context, final K newKey) {CacheEntry<K,V> result = null;// 超過限制,執行移除if(isNeedEvict(context)) {K evictKey = queue.remove();keySet.remove(evictKey);// 移除最開始的元素V evictValue = doEvictRemove(context, evictKey);result = new CacheEntry<>(evictKey, evictValue);}return result;}@Overridepublic void updateKey(ICacheContext<K, V> context, K key) {if (!keySet.contains(key)) {queue.add(key);keySet.add(key);}}}

這里雖然可以解決 fifo 的刪除問題,但是內存有點浪費。

而且這樣其實順序也太對,每次還是需要更新 queue 的位置。

我們把結構繼續調整一下,用其他的數據結構來替代。

v1.0.1 實現

其他的方式

方案數據結構內存開銷實現難度是否推薦
Queue + Set兩個結構較大簡單?
LinkedHashSet單結構簡單? 推薦
LinkedHashMapMap+鏈表中等中等? 可選

實現

簡單起見,我們使用 LinkedHashSet 來實現。

package com.github.houbb.cache.core.support.evict.impl;import com.github.houbb.cache.api.ICacheContext;
import com.github.houbb.cache.core.model.CacheEntry;
import com.github.houbb.cache.core.support.evict.AbstractCacheEvict;import java.util.*;/*** 丟棄策略-先進先出* @author binbin.hou* @since 0.0.2*/
public class CacheEvictFifo<K,V> extends AbstractCacheEvict<K,V> {/*** queue 信息* @since 0.0.2*/private final Set<K> accessOrder = new LinkedHashSet<>();;@Overridepublic CacheEntry<K,V> doEvict(ICacheContext<K, V> context, final K newKey) {CacheEntry<K,V> result = null;// 超過限制,執行移除if(isNeedEvict(context)) {Iterator<K> iterator = accessOrder.iterator();K evictKey = iterator.next();V evictValue = doEvictRemove(context, evictKey);iterator.remove();// 移除最開始的元素result = new CacheEntry<>(evictKey, evictValue);}return result;}@Overridepublic void updateKey(ICacheContext<K, V> context, K key) {accessOrder.remove(key);accessOrder.add(key);}}

這樣我們的目標算是達成了,實現了內存和性能的平衡。

拓展信息

開源矩陣

下面是一些緩存系列的開源矩陣規劃。

名稱介紹狀態
resubmit防止重復提交核心庫已開源
rate-limit限流核心庫已開源
cache手寫漸進式 redis已開源
lock開箱即用的分布式鎖已開源
common-cache通用緩存標準定義已開源
redis-config兼容各種常見的 redis 配置模式已開源
quota-server限額限次核心服務待開始
quota-admin限額限次控臺待開始
flow-control-server流控核心服務待開始
flow-control-admin流控控臺待開始

手寫 Redis 系列

java從零手寫實現redis(一)如何實現固定大小的緩存?

java從零手寫實現redis(三)redis expire 過期原理

java從零手寫實現redis(三)內存數據如何重啟不丟失?

java從零手寫實現redis(四)添加監聽器

java從零手寫實現redis(五)過期策略的另一種實現思路

java從零手寫實現redis(六)AOF 持久化原理詳解及實現

java從零手寫實現redis(七)LRU 緩存淘汰策略詳解

java從零開始手寫redis(八)樸素 LRU 淘汰算法性能優化

java從零開始手寫redis(九)LRU 緩存淘汰算法如何避免緩存污染

java從零開始手寫redis(十)緩存淘汰算法 LFU 最少使用頻次

java從零開始手寫redis(十一)緩存淘汰算法 COLOK 算法

java從零開始手寫redis(十二)過期策略如何實現隨機 keys 淘汰

java從零開始手寫redis(十三)redis漸進式rehash詳解

java從零開始手寫redis(十四)JDK HashMap 源碼解析

java從零開始手寫redis(十四)JDK ConcurrentHashMap 源碼解析

java從零開始手寫redis(十五)實現自己的 HashMap

java從零開始手寫redis(十六)實現漸進式 rehash map

java從零開始手寫redis(十七)v1.0.0 代碼重構+拓展性增強

java從零開始手寫redis(十八)緩存淘汰算法 FIFO 優化

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/86108.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/86108.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/86108.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

用Zynq實現脈沖多普勒雷達信號處理:架構、算法與實現詳解

用Zynq實現脈沖多普勒雷達信號處理:架構、算法與實現詳解 脈沖多普勒(PD)雷達是現代雷達系統的核心技術之一,廣泛應用于機載火控、氣象監測、交通監控等領域。其核心優勢在于能在強雜波背景下檢測運動目標,并精確測量其徑向速度。本文將深入探討如何利用Xilinx Zynq SoC(…

OpenCV CUDA模塊設備層-----線程塊級別的一個內存填充工具函數blockFill()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 在同一個線程塊&#xff08;thread block&#xff09;內&#xff0c;將 [beg, end) 范圍內的數據并行地填充為指定值 value。 它使用了 CUDA 線程…

SAP-ABAP:如何查詢 SAP 事務碼(T-Code)被包含在哪些權限角色或權限對象中

要查詢 SAP 事務碼&#xff08;T-Code&#xff09;被包含在哪些權限角色或權限對象中&#xff0c;可使用以下專業方法&#xff1a; &#x1f50d; 1. 通過權限瀏覽器 (SUIM) - 最推薦 事務碼&#xff1a;SUIM (權限信息系統) 操作步驟&#xff1a; 執行 SUIM → 選擇 “角色…

MySQL 多列 IN 查詢詳解:語法、性能與實戰技巧

在 MySQL 中&#xff0c;多列 IN 查詢是一種強大的篩選工具&#xff0c;它允許通過多字段組合快速過濾數據。相較于傳統的 OR 連接多個條件&#xff0c;這種語法更簡潔高效&#xff0c;尤其適合批量匹配復合鍵或聯合字段的場景。本文將深入解析其用法&#xff0c;并探討性能優化…

自由學習記錄(63)

編碼全稱&#xff1a;AV1&#xff08;Alliance for Open Media Video 1&#xff09;。 算力消耗大&#xff1a;目前&#xff08;截至 2025 年中&#xff09;軟件解碼 AV1 的 CPU 開銷非常高&#xff0c;如果沒有專門的硬件解碼單元&#xff0c;播放高清視頻時會很吃 CPU&#…

日本生活:日語語言學校-日語作文-溝通無國界(4)-題目:喜歡讀書

日本生活&#xff1a;日語語言學校-日語作文-溝通無國界&#xff08;4&#xff09;-題目&#xff1a;喜歡讀書 1-前言2-作文原稿3-作文日語和譯本&#xff08;1&#xff09;日文原文&#xff08;2&#xff09;對應中文&#xff08;3&#xff09;對應英文 4-老師評語5-自我感想&…

C++優化程序的Tips

轉自個人博客 1. 避免創建過多中間變量 過多的中間變量不利于代碼的可讀性&#xff0c;還會增加內存的使用&#xff0c;而且可能導致額外的計算開銷。 將用于同一種情況的變量統一管理&#xff0c;可以使用一種通用的變量來代替多個變量。 2. 函數中習慣使用引用傳參而不是返…

C#Blazor應用-跨平臺WEB開發VB.NET

在 C# 中實現 Blazor 應用需要結合 Razor 語法和 C# 代碼&#xff0c;Blazor 允許使用 C# 同時開發前端和后端邏輯。以下是一個完整的 C# Blazor 實現示例&#xff0c;包含項目創建、基礎組件和數據交互等內容&#xff1a; 一、創建 Blazor 項目 使用 Visual Studio 新建項目 …

前端的安全隱患之API惡意調用

永遠不要相信前端傳來的數據&#xff0c;對于資深開發者而言&#xff0c;這幾乎是一種本能&#xff0c;無需過多解釋。然而&#xff0c;初入職場的開發新手可能會感到困惑&#xff1a;為何要對前端傳來的數據持有如此不信任的態度&#xff1f;難道人與人之間連基本的信任都不存…

基于 Spark 實現 COS 海量數據處理

上周在組內分享了一下這個主題&#xff0c; 我覺得還是摘出一部分當文章輸出出來 分享主要包括三個方面&#xff1a; 1. 項目背景 2.Spark 原理 3. Spark 實戰 項目背景 主要是將海量日志進行多維度處理&#xff1b; 項目難點 1、數據量大&#xff08;壓縮包數量 6TB,60 億條數…

Unity3D 屏幕點擊特效

實現點擊屏幕任意位置播放點擊特效。 屏幕點擊特效 需求 現有一個需求&#xff0c;點擊屏幕任意位置&#xff0c;播放一個點擊特效。 美術已經做好了特效&#xff0c;效果如圖&#xff1a; 特效容器 首先&#xff0c;畫布是 Camera 模式&#xff0c;畫布底下有一個 UIClic…

MCU編程

MCU 編程基礎&#xff1a;概念、架構與實踐 一、什么是 MCU 編程&#xff1f; MCU&#xff08;Microcontroller Unit&#xff0c;微控制器&#xff09; 是將 CPU、內存、外設&#xff08;如 GPIO、UART、ADC&#xff09;集成在單一芯片上的小型計算機系統。MCU 編程即針對這些…

Go語言--語法基礎6--基本數據類型--數組類型(1)

Go 語言提供了數組類型的數據結構。 數組是具有相同唯一類型的一組已編號且長度固定的數據項序列&#xff0c;這種類型可以是任意的 原始類型例如整型、字符串或者自定義類型。相對于去聲明number0,number1, ..., and number99 的變量&#xff0c;使用數組形式 numbers[0], …

左神算法之給定一個數組arr,返回其中的數值的差值等于k的子數組有多少個

目錄 1. 題目2. 解釋3. 思路4. 代碼5. 總結 1. 題目 給定一個數組arr&#xff0c;返回其中的數值的差值等于k的子數組有多少個 2. 解釋 略 3. 思路 直接用hashSet進行存儲&#xff0c;查這個值加上k后的值是否在數組中 4. 代碼 public class Problem01_SubvalueEqualk {…

自回歸(AR)與掩碼(MLM)的核心區別:續寫還是補全?

自回歸(AR)與掩碼(MLM)的核心區別:用例子秒懂 一、核心機制對比:像“續寫”還是“完形填空”? 維度自回歸(Autoregressive)掩碼語言模型(Masked LM)核心目標根據已生成的token,預測下一個token(順序生成)預測句子中被“掩碼”的token(補全缺失信息)輸入輸出輸入…

后端開發兩個月實習總結

前言 本人目前在一家小公司后端開發實習差不多兩個月了&#xff0c;現在準備離職了&#xff0c;就這兩個月的實習經歷寫下這篇文章&#xff0c;既是對自己實習的一個總結&#xff0c;也是給正在找實習的小伙伴以及未來即將進入到后端開發這個行業的同學的分享一下經驗。 一、個…

Python基礎(??FAISS?和??Chroma?)

??1. 索引與查詢性能? ??指標????FAISS????Chroma????分析????索引構建速度??72.4秒&#xff08;5551個文本塊&#xff09;91.59秒&#xff08;相同數據集&#xff09;FAISS的底層優化&#xff08;如PQ量化&#xff09;加速索引構建&#xff0c;適合批…

Windows下memcpy_s如何在Linux下使用

Windows下代碼如下 memcpy_s(pLine->ppBuf[i], m_ColorLineByte, pIn nOffset, m_ColorLineByte); 方案 1&#xff1a;使用標準 memcpy 手動檢查&#xff08;最通用&#xff09; // 檢查參數有效性 if (pLine->ppBuf[i] nullptr || pIn nullptr || m_ColorLi…

2025年數學算法與自動化控制國際會議(ICMAAC 2025)

2025年數學算法與自動化控制國際會議&#xff08;ICMAAC 2025&#xff09; 2025 International Conference on Mathematical Algorithms and Automation Control 一、大會信息 會議簡稱&#xff1a;ICMAAC 2025 大會地點&#xff1a;中國長沙 審稿通知&#xff1a;投稿后2-3日…

C語言數組介紹 -- 一維數組和二維數組的創建、初始化、下標、遍歷、存儲,C99 變長數組

目錄 1. 一維數組 1.1 數組的概念 1.2 一維數組的創建 1.3 一維數組的初始化 1.4 數組的類型 1.5 數組下標 1.5.1 數組元素的遍歷 1.5.2 數組的輸入 1.6 一維數組在內存中的存儲 1.7 sizeof 計算數組元素個數 2. 二維數組 2.1 二維數組的創建 2.2 二維數組的初始…