项目简介

大家好,我是老马。

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 二维数组的初始…