CDN缓存替代算法

CDN缓存工作过程如下:用户发出一个请求,如果请求被命中,缓存将对用户的请求进行响应,返回其请求的数据;如果未被命中,缓存向上拉取用户需要的数据,并对其存储的数据进行替换。

缓存算法的意义在于,根据用户的请求习惯,对于缓存种的数据进行更新,使得用户据请求的命中率提高,缩短整体响应用户请求延时,同时提高高峰时间网络所能承受的访问容量。

现有的缓存替代算法主要思路有下面几种:
1、基于访问频率,通过某段时间内对资源被访问的次数进行统计,以此判断该资源接下来是否被访问,典型算法:LFU、2Q、LIRS
2、基于访问时间,通过i记录资源访问的时间,以时间做判断,典型算法:LRU
3、访问时间与访问频率相结合,典型算法:LRFU、FBR
CDN缓存算法具体有五种典型算法:
1、“最近最少使用”缓存算法
2、“最少频率使用”缓存算法
3、“基于分数因子”缓存算法
4、“块等级”缓存算法

Least Recently Used算法

缓存将保留最近一段时间内经常使用的数据,而淘汰最近未被经常使用的数据。
基于事实:最近一段时间内经常被访问的数据在未来一段时间内也会被访问
简单版本的实现可以参考https://leetcode-cn.com/problems/lru-cache/
缺点:最近被访问的内容不一定是最热门的,这将导致一些冷门内容留在缓存种,影响用户访问内容和服务响应用户的效率。
另外可以看看mysql里面对于lru的改进:MySQL——Innodb改进LRU算法

Least Frequency Used算法

该算法按照内容的访问频率对内容进行排序。
缓存一般被分为两部分:固定缓存(AC,Actual Cache)和隐藏缓(SC,Shadow Cache)
固定缓存是更新不频繁,资源变动较少的那部分缓存
隐藏缓存是更新频繁,资源变动较大的那部分缓存
当用户发出访问请求时,未命中的内容将先被存储到SC种。在一定时间间隔T内,缓存中会维持一个频率列表,记录每个内容被访问的次数。T时间过去之后,{AC,SC}种被请求次数最多的内容将会被更新到AC中,在下一轮T之内,AC中内容不会被替换掉。
基于事实:内容被访问的频率能够反映内容的热门程度。AC和SC的增加使得最少频率的准确率得到提高
缺点:计算频率的时间段T的大小不好控制,AC和SC的容量不好控制,替换时间设定不好控制
简单版本的实现可以参考:
https://leetcode-cn.com/problems/lfu-cache/solution/lfuhuan-cun-by-leetcode-solution/
代码如下:

// 缓存的数据结构
struct cacheNode {int cnt;    // 缓存使用的频率int time;   // 缓存使用的时间int key;    // 缓存的键int value;  // 缓存的值cacheNode(int _cnt, int _time, int _key, int _value) {cnt = _cnt;time = _time;key = _key;value = _value;}// 实现一个cacheNode的比较函数// 频率小的排前面,如果频率一样,时间短的排前面bool operator< (const cacheNode& rhs) const {return cnt == rhs.cnt ? time < rhs.time : cnt < rhs.cnt;}};
class lfuCache {
private:// 缓存的容量,时间数int capcity;int time;std::unordered_map<int, cacheNode> keyTable;std::set<cacheNode> balanceTree;
public:lfuCache(int cap) {capcity = cap;time = 0;keyTable.clear();balanceTree.clear();}int get(int key) {if (capcity == 0) return -1;auto it = keyTable.find(key);if (it == keyTable.end()) return -1;cacheNode cache = it->second;balanceTree.erase(cache);cache.cnt += 1;cache.time = ++time;balanceTree.insert(cache);it->second = cache;return cache.value;}void put(int key, int value) {if (capcity == 0) return;auto it = keyTable.find(key);if (it == keyTable.end()) {if (keyTable.size() == capcity) {keyTable.erase(balanceTree.begin()->key);balanceTree.erase(balanceTree.begin());}cacheNode cache = cacheNode(1, ++time, key, value);keyTable.insert(std::make_pair(key, cache));balanceTree.insert(cache);} else {cacheNode cache = it->second;balanceTree.erase(cache);cache.cnt += 1;cache.time = ++time;cache.value = value;balanceTree.insert(cache);it->second = cache;}}
};

Scoring based Caching算法

1、定义:对每一个视频(Vi),都维护一个分数(Si)。每个视频i在被放入缓存时,都会得到一个初始化分数Si = B。
每一次视频i被请求,该视频都会得到一个新的分数,而其余视频分数也会相应调整:Si = Si + A,其余视频Sk = Sk - 1(k != i)
2、替换规则:在维护一个分数上,有两种替换策略:

  • 区间分数法:定义一个有效分数区间【M,N】。若某个视频的分数在这个区间内,且不再缓存中,则把这个视频放入缓存。如果某个在缓存中的视频的分数不在这个区间内,则在缓存中删除该视频
  • 最优分数法:根据一个节点的最大存储能力,如能存L个视频,选择最优分数的内容进行缓存。每次有一部视频的分数有改变,则进行排序,凡分数不在前L的视频从缓存中删除,凡分数在前L的视频加入缓存中

3、请求处理:对于每个CDN视频的请求,会出现以下三种处理事件

  • 1、请求的视频已在缓存中,请求命中。此时只需要对视频的分数做出调整,不需要在缓存中删除内容,也不需要向上级节点请求内容。CDN内部没有流量消耗
  • 2、请求的视频不在缓存中而算法要求节点缓存该视频。节点向上级节点赋值被请求的视频,然后在复制之后向用户发送被请求的视频,将视频加入缓存,调整分数。此时CDN内部有流量消耗,边缘节点向中心节点复制了视频内容
  • 3、请求的视频不在缓存中而算法不要求节点缓存该视频,调整分数,不需要从中心点复制内容,请求被转发到中心节点。CDN内部没有流量消耗

4、其他
1、一般来说,节点应该维护每一部视频的分数,但实际上分数过低的视频,一般不维护分数,而是从关注列表中移除
2、Shadow Cache。每个节点存储能力被分为两个部分。较大的部分用来存储内容,较小的部分用来存储视频列表、分数等与管理有关的内容。两个存储空间严格分开。宏观上看,节点有部分存储能看不可见,称为Shadow Cache
最后,基于分数因子的缓存算法不是一个独立的算法,而是其他算法的基础或者框架。例如LRU和LFU可以看作对于分数不同定义的最优分数法的分数因子缓存。

Chunk-level Caching算法

1、定义:基于块等级的缓存算法, 时在分数因子缓存算法基础上,把每个视频分成大小相同、内容连续的k块分别存储,然后每个视频块的分数Sk继承原视频的分数Si。定义第i个视频的第k块视频的分数为Si,k
2、计分策略
每部视频被访问,则对视频i内的所有块都进行+1:Si,k = Si,k +1
若第k块被完整观看,则Si,k = Si,k + 1
若停止观看(退出、快进、快退),则说明用户对该块不感兴趣,则Si,k = Si,k - 1;
3、请求处理
大部分时候,块等级的缓存算法,与基于分数因子的缓存算法十分相像,即上面SC出现的3种请求处理的情况都会出现。不同之处在于之前是比较Si来进行取舍,现在是比较Si,k。
4、其他
基于块等级的缓存算法,主要用于单个内容较大的内容分发网络,如视频分发网络。它考虑了以下一个事实,即人们可能对视频的某一段感兴趣,把整个视频存储下来会产生浪费;或者人们只浏览了视频的开头,就会选择看或者不看。因此,在计分规则中,充分考虑了这些事实。
① 一个用户请求了某个视频,则可能对这个视频的其他部分都感兴趣,因此计分策略1体现了这个需求。
② 一个用户看完了某一块,则可能不会再回去看了,因此计分策略2体现了这个需求。
③ 一个用户停止观看某段视频,则可能不会再看这段视频之后的其他视频块,因此计分策略3体现了这个需求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/376872.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端开发常用正则表达式

1、电话 var phone /(^[^1][0-9\-]{6,20}$)|(^(134|135|136|137|138|139|150|151|152|157|158|159|182|183|187|188|147|130|131|132|155|156|185|186|145|133|153|180|189|181|184)\d{8}$)/ 2、邮箱 var email /^([a-zA-Z0-9_.-])([a-zA-Z0-9_-])((\.[a-zA-Z0-9_-]{2,3}){1,…

android 中调用接口发送短信

转载&#xff1a;http://ziyu-1.iteye.com/blog/1013932 android中可以通过两种方式发送短信 第一&#xff1a;调用系统短信接口直接发送短信&#xff1b;主要代码如下&#xff1a; Java代码//直接调用短信接口发短信 SmsManager smsManager SmsManager.getDefault(); List…

linux 命令案例学习——文件搜索

两个搜索文件的工具 locate ——仅仅通过文件名查找文件find ——依据文件的各种属性在既定目录&#xff08;包括子目录&#xff09;里查找一个通常与文件搜索命令一起使用、处理搜索结果文件列表的命令 xargs1 locate 1.1 查找文件名中含有zip的文件名 locate zip 看下结…

Redis 缓存击穿、缓存穿透、缓存雪崩的处理方法

常用的分布式缓存Redis单机并发量能达到万级&#xff0c;常用的关系型数据库MySQL一般并发量是千级&#xff0c;他们支持的并发量可能差十倍&#xff0c;所以要尽可能把流量拦截在缓存层。 缓存击穿 一个并发访问量比较大的key在某个时间过期&#xff0c;导致所有的请求直接打…

Java-- 异常与记录日志

可以使用java.util.logging工具将输出记录在日志中。记录日志的的功能还是很简单的&#xff0c;下面直接铺出代码&#xff1a; 1 package com.exceptions;2 3 import java.io.*;4 import java.util.logging.Logger;5 6 class LoggingException extends Exception{7 private…

图像处理基础

图像处理基础 在计算机中&#xff0c;按照颜色和灰度的多少可以将图像分为二值图像、灰度图像、索引图像和真彩色RGB图像四种基本类型。目前&#xff0c;大多数图像处理软件都支持这四种类型的图像。 (1) 二值图像&#xff1a;一幅二值图像的二维矩阵仅由0、1两个值构成&#x…

缓存一致性解决方法

对于缓存 数据库读写&#xff0c;有个经典的Cache Aside Pattern&#xff1a; 读取&#xff1a;先读取缓存&#xff0c;缓存里没有&#xff0c;读取数据库&#xff0c;然后返回响应&#xff0c;顺便保存缓存&#xff1a; 更新&#xff1a;先更新数据库&#xff0c;然后删除缓…

使用SpringMVC的表单验证

上一篇搭建了基本项目&#xff0c;这一篇在此基础上加入表单验证功能。 第一步&#xff0c;添加command类 Java代码 package test.bean; import javax.validation.constraints.Size; public class User { Size(min3,max30) private String username; …

hdu1247(Hat’s Words)

我以为像a、aa这样的输入应该是没有输出的&#xff0c;结果还是要输出aa。 建树的时候就是常规建树&#xff0c;不过查找的时候要做一些变形&#xff1a;对于一个单词&#xff0c;从第一位检查有没有单词是它的前缀&#xff0c;如果有的话&#xff0c;再去检查它的后半部分是不…

单体、分布式、微服务、Serverless软件架构一览

目录软件架构单体架构分布式应用微服务架构Serverless架构总结Reference软件架构 软件架构就是软件的基本结构&#xff0c;合适的架构是软件成功的最重要因素之一。这里列举了目前流行的4种软件架构。 单体架构 典型的三级架构&#xff1a;前端&#xff08;web/手机端&#…

MyBatis3 association error - The content of element type resultMap must match (constructor?,id*,r...

MyBatis3 association error - The content of element type "resultMap" must match "(constructor?,id*,result*,association*,collection*,discriminator?)" 1.后台错误信息-问题现象&#xff1a; ERROR [geby:Context initialization failed] 2013-0…

Midjourney V6刷屏,但它最可怕的地方居然不是那些神图?

Midjourney在沉寂九个月后推出了Midjourney V6&#xff0c;这个文生图产品体现出的更细腻的细节处理&#xff0c;更强大的语言理解能力和更加“不像AI”的图片效果在过去几天引发一片惊呼。 作为一个闭源的模型产品&#xff0c;Midjourney的魔法配方并不为人所知&#xff0c;但…

HTTP 错误500.19 -Internal Server Error

HTTP 错误500.19 -Internal Server Error 原文:HTTP 错误500.19 -Internal Server Error HTTP 错误500.19 -Internal Server Error 错误代码 0x80070021 asp.net 2009-11-05 16:54:33 阅读484 评论1 字号&#xff1a;大中小 错误摘要 HTTP 错误500.19 -Internal Server Error …

连续内存分区式内存管理

目录前言分区式内存管理动态分区内存管理总结本笔记参考黄工的https://mp.weixin.qq.com/s/k0W_LqI1zBAYC1GU1U2HQA 前言 内存管理模块主要负责内存的初始化、分配以及释放。 从分配内存是否连续可以分为两大类&#xff1a; 1、连续内存管理 为进程分配的内存空间是连续的&a…

用DEVC++作图

小海豚学NOIP&#xff0c;老师说要用DEV C。 小海豚喜欢画图&#xff0c;记得以前用C#编些程序给她看。可前一阵打开看&#xff0c;我的免费Visual Studio过期了。可恶的Microsoft &#xff0c;不想用盗版难道就要每个月就下载一次&#xff1f; 于是就用DEV C的Windows调用吧。…

Python服务器开发三:Socket

Python服务器开发三&#xff1a;Socket socket是操作系统中I/O的延续&#xff0c;它可以使进程和机器之间的通信成为可能。socket可以看成一个标准的文件描述符。不同的是文件需要用open()函数打开&#xff0c;而socket用socket() 函数建立.recv()、send()函数和read()、write(…

Syntax error: Bad for loop variable解决办法

在Ubuntu下写的shell文件t.sh执行时出现错误&#xff1a; 1 t.sh: 6: Syntax error: Bad for loop variable 从ubuntu 6.10开始&#xff0c;ubuntu就将之前默认的bash shell更换成了dash shell&#xff0c;其表现为/bin/sh链接倒了/bin/dash&#xff0c;而不是传统的/bin/bash&…

Linux命令常见

摘自&#xff1a; 常考的 21 条 Linux 命令 目录&#xff09;cd,切换路径ls,查看文件与目录的命令cp,用于复制文件mv,用于移动文件、目录cat,查看文件内容find&#xff0c;文件搜索文件权限命令&#xff0c; 设置权限&#xff0c;-取消权限文本处理命令打包和压缩文件命令进程相…

记一次调试

这是我最近几个月来遇到的最棘手的一个问题&#xff1a;* 昨天花了4个小时找出第一层次的原因这个纠结啊&#xff0c;本来和老婆说好准时下班回家吃饭的&#xff0c;结果被这个问题拖了老久。这是一个gradle的plugin&#xff0c;用来resolve公司内部的dependency的&#xff0c;…

OSGi.NET 学习笔记 [模块化和插件化][小结]

【目录】-【模块化和插件化】-【小结】 现在我们来对OSGi.NET的“模块化和插件化”做一个小结&#xff0c;再次把官方的说明拿出来  1&#xff09; 物理隔离&#xff1a;基于UIOSP开发的模块是一个物理隔离的可单独部署的模块&#xff0c;每一个模块拥有独立的文件夹、类型空…