各种缓存介绍

说起缓存相关技术,老多了, memcache、redis、squid、varnish、web cache、 CDN等等。缓存技术五花八门,但这些技术间有什么共性的地方,又有什么不同的地方呢?答案肯定是有的,这次为大家分享及整理一下缓存方面的技术,主要分为三个系列展开:

缓存随谈系列之一:数据库缓存

缓存随谈系列之二:静态缓存

缓存随谈系列之三:动态缓存
一、什么是数据库缓存

我们知道常见的数据库,比如oracle、mysql等,数据都是存放在磁盘中。虽然在数据库层也做了对应的缓存,但这种数据库层次的缓存一般针对的是查询内容,而且粒度也太小,一般只有表中数据没有变更的时候,数据库对应的cache才发挥了作用。但这并不能减少业务系统对数据库产生的增、删、查、改的庞大IO压力。所以数据库缓存技术在此诞生,实现热点数据的高速缓存,提高应用的响应速度,极大缓解后端数据库的压力。

以下为memcache数据库缓存为例,以图说明一下什么是数据库缓存:

022f6d6489e6facab3ee148f0150bdc7aa5bfe32

二、数据库缓存的技术特点

性能优越

数据库缓存的第一个技术特点就是提高性能,所以数据库缓存的数据基本上都是存储在内存中,相比io读写的速度,数据访问快速返回。而且在mysql 5.6的版本开始,已经把memcache这种跟数据库缓存直接挂钩的中间件直接集成进去了,已经等不及我们自己去单独部署对应数据库缓存的中间件了。

应用场景

针对数据库的增、删、查、改,数据库缓存技术应用场景绝大部分针对的是“查”的场景。比如,一篇经常访问的帖子/文章/新闻、热门商品的描述信息、好友评论/留言等。因为在常见的应用中,数据库层次的压力有80%的是查询,20%的才是数据的变更操作。所以绝大部分的应用场景的还是“查”缓存。当然,“增、删、改”的场景也是有的。比如,一篇文章访问的次数,不可能每访问一次,我们就去数据库里面加一次吧?这种时候,我们一般“增”场景的缓存就必不可少。否则,一篇文章被访问了十万次,代码层次不会还去做十万次的数据库操作吧。

数据一致性

在很多应用场景中,当一个数据发生变更的时候,很多人在考虑怎么样确保缓存数据和数据库中数据保存一致性,确保从缓存读取的数据是最新的。甚至,有人在对应数据变更的时候,先更新数据库,然后再去更新缓存。我觉得这个考虑不太现实,一方面这会导致代码层次逻辑变得复杂,另外一方面也真想不明白还要缓存干什么了。在绝大多数的应用中,缓存中的数据和数据库中的数据是不一致的。即,我们牺牲了实时性换回了访问速度。比如,一篇经常访问的帖子,可能这篇帖子已经在数据库层次进行了变更。而我们每次访问的时候,读取的都是缓存中的数据(帖子)。既然是缓存,那么必然是对实时性可以有一定的容忍度的数据,容忍度的时间可以是5分钟,也可以是5小时,取决于业务场景的要求。相反,一定要求是实时性的数据库,就不应该从缓存里读取,比如库存,再比如价格。

高可用

自从有了缓存,代码每天快乐的去缓存中愉快的玩耍。为什么说高可用呢,我们知道缓存为数据库抵挡了很多压力,同时也为应用提供了良好的访问速度。但同时有没有想过缓存的感受,如果当数据库缓存“罢工”了,这会出现什么后果?特别在一些高并发的应用中,数据库层肯定是“消化不良“,最终导致应用全面崩溃。所以缓存的高可用显得非常重要。
三、数据库缓存常见开源技术

要说用于数据库缓存场景的开源技术,那必然是memcache和redis这两个中间件。

74ba1c9a1c6cd0a7d59872b5b8e77f366ff6ce50

因为都是专注于内存缓存领域,memcache和redis向来都有争议。比如性能,到底是memcache性能好,还是redis性能更好等。同样都是内存缓存技术,它们都有自己的技术特性。没有更好的技术,只有更合适的技术。个人总结一下,有持久化需求或者对数据结构和处理有高级要求的应用,选择redis。其他简单的key/value存储,选择memcache。所以根据自身业务特性,数据库缓存来选择适合自己的技术。

暂不说用不用数据库缓存,见过有人把session存储在数据库中的,也见过把视频/文件转化成二进制存储在数据库的,这种行为无疑是逆天的。合理应用数据库缓存技术,且行且珍惜,切勿走向误区。

静态缓存

上次写了一篇数据库缓存,由于快餐式的风格,遭到了广大读友的吐槽。上篇风格有点 “ 虚 ”,我本身是一个技术控,偏向经验/干货的分享,本文主要描述静态缓存方面的一些心得及分享。作为系列二,有所不足之处,依旧希望大家踊跃“ 亮砖 ”。

说起静态缓存技术,CDN是经典代表之作。静态缓存技术面非常广,涉及的开源技术包含apache、Lighttpd、nginx、varnish、squid等。

静态缓存,一般指 web 类应用中,将图片、js、css、视频、html等静态文件/资源通过磁盘/内存等缓存方式,提高资源响应方式,减少服务器压力/资源开销的一门缓存技术。

本文主要通过:浏览器缓存、磁盘缓存、内存缓存、nginx的内存缓存、CDN五个方面围绕静态缓存而展开。

一、浏览器缓存

浏览器缓存,也称为客户端缓存,是静态缓存中最常见最直接的表现形式,很多时候都往往被人忽略掉。

案例1:

我们经常在nginx的配置文件中看到以下缓存配置:
在这里插入图片描述
案例2:

在经常写 jsp 的时候,html 标签中关于 http 头信息也可以注意到“ expires ”的字样:
在这里插入图片描述
对于案例1和案例2中(nginx设置的expires优先级大于代码中设置的expires优先级),expires是给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。此种方法非常适合不经常变动的资源。如果文件变动较频繁,就不要使用 expires 来缓存。

比如对于常见类web网站来说,css 样式和 js 脚本基本已经定型,所以最适合的方法是 expires 来缓存一些内容到访问者浏览器。
案例3:

通过 chrome 访问服务器端的一张图片,用F12键打开开发者前端调试工具:
在这里插入图片描述
第一次访问,响应200状态,当第二次及后续访问的时候,变成304状态,客户端已经开始获取浏览器缓存内容,而不需要去服务器端获取对应的请求内容,即 nginx 中 expires 参数设置已经生效。等待客户端缓存时间过期后,会再次请求服务器端内容来更新本地缓存。
在这里插入图片描述
介绍到这里,突然想起一个有意思的需求。比如,访问一张静态文件,不想客户端缓存,需要每次都去服务器端取数据。我们可以用“ last-modified ”参数来实现,即“ last-modified ”是根据文件更新时间来确定是否再次发送加载。

Nginx核心配置如下:
在这里插入图片描述
我们更改掉服务器传回客户端的“ last-modified ”文件修改时间参数的值,这样导致客户端本地保存的文件时间每次跟服务器端传回来的时间不一致,所以每次客户端“ 误认为 ”服务器端有静态文件更新,每次都会去服务器端取“ 所谓的最新数据 ”。这样我们可以看到,不管在浏览器访问多少次,返回的 http 状态都是200,再也找不到304状态了。

误区:在 nginx 中设置 expires,并不是指把静态内容缓存在 nginx 中,而是设置客户端浏览器缓存的时间,这是很多人的误区所在。
二、磁盘缓存

除了存储在客户端的静态缓存(浏览器静态)技术外,在服务器端的静态缓存技术主要分为磁盘缓存和内存缓存两大类。单纯围绕 nginx 的 squid、varnish 等一类中间件,处理静态数据的性能十分优秀。核心是 nginx 基于 epoll 网络模型,而相比 apache 基于 select 网络模型。所以 apache 的优势在于密计算型,稳定性好。而 nginx 偏向静态处理,反向代理,高并发。比如 apache+php 的稳定性比 nginx+php 要好,而性能是明显 nginx 要优秀许多。

以上仅单纯是对磁盘中静态数据处理的能力,所谓磁盘缓存,指另外的一种缓存静态文件的技术。以 nginx 配置为例:
在这里插入图片描述
可以看出 nginx 主要通过 proxy_cache 来实现 web cache,熟悉 nginx 的同学,不难看出,以上配置在 location 这里,不仅可以实现静态文件的缓存,还可以实现动态文件的缓存(这里放在下章节详细介绍)。我们编写个 test.html测试文件,然后并访问。test.html 源码如下:
在这里插入图片描述
我们发现服务器的 cache 目录里面,多了两个缓存文件:
在这里插入图片描述
有意思的,这两个文件里面的内容分别为(通过 less 命令查看):
在这里插入图片描述
(b0ad5d3e7f099bfff9e4fc6a159d868c)
在这里插入图片描述
(53edc39ed253e14415a29412cfc01faf)

所以不难看出,nginx 把 html 内容和图片二进制全部缓存到本地磁盘上了。下次用户再次来访问 test.html 的时候,nginx 直接将缓存在本地磁盘的文件返回给用户。特别是后端如若是部署的 tomcat、iis 等,nginx 强大的静态缓存能力,有效减少了服务器压力。
三、内存缓存

紧接上面描述的磁盘缓存,内存缓存顾名思义,就是把静态文件缓存在服务器端的内存中。所以这种缓存,如若命中缓存的话,取内存中的缓存数据返回比取磁盘中的缓存数据返回,性能要高很多。以 varnish 为例,varnish 核心配置如下:

启动命令:

在这里插入图片描述
参数简介:
在这里插入图片描述
default.vcl核心配置如下:
在这里插入图片描述
Varnish对.gif、.jpg、.jpeg、.png等结尾的 URL 缓存时间设置1小时。varnish设置完毕后,我们用命令行方式,通过查看网页头来查看命中情况:

在这里插入图片描述
在这里插入图片描述
最后,我们可以通过 varnishadm 命令来清理缓存,也可以通过 varnishstat 命令来查看 varnish 系统缓存状态。
四、Nginx 的内存缓存

以上主要以 Varnish 为例,介绍了内存缓存静态资源的方法。其实 nginx 也有内存缓存,相比 squid、varnish 而言,nginx 的内存缓存需要通过编码实现。如下配置:
在这里插入图片描述
memcached_pass 指定服务器地址,使用变量 $memcache_key 为 key 查询值,去 memcache 查询对应 value 值。

如我们访问:http://***.***.***.***/image/test.jpg ,则 nginx 去 memcache 中查询key 为“ test.jpg ”的 value 值并返回。如果没有相应的值,则返回 error_page 404。介绍到这里,关键在于存储在 memcache 中的静态文件,需要通过代码写入 memcache 中。怎么样通过 php/java 等代码把静态资源的数据写入 memcache 中,关于这块的示例就不再过多介绍了。

Nginx的内存缓存因为需要通过编码实现,所以灵活性特别高。这块可以结合自身业务系统的特点,让静态缓存的灵活性和效率都能得到保障。可能唯一的缺陷就是,通过编码实现的方式,给我们维护管理带来了负担。在之前我曾参与的一个电商系统,就是把客户的订单照片通过 php 代码写入 memcache,客户访问取图的时候,从 memcache 中获取,速度效率特别高。Nginx 作为一款在七层无所不能且轻量级高性能的中间件,能够直接去 memcache 中取数据,来实现静态缓存的效果,这块相应的功能是其他软件无法相媲美的。
五、CDN

说起 CDN,大家都不陌生,它是静态缓存加速最典型的代表。CDN技术并不是一门新的技术,它是基于传统 nginx、squid、varnish 等 web 缓存技术,结合 DNS 智能解析的静态缓存加速技术。值得注意的是,他对动态链接访问并没有加速效果。架构原理图如下:
在这里插入图片描述
所以CDN的静态缓存技术核心主要在于两点:

节点缓存:对需要加速的网站应用,相应的静态资源通过内存缓存+磁盘缓存的方式缓存在服务器端。

精准调度:对访问的用户 ip 进行智能解析调度,实现就近缓存节点访问。比如以上图例中,北京用户访问 www.a.com。通过 dns 解析的时候,分析用户 ip,发现是北京用户。则 dns 返回对应北京缓存节点的 ip 地址给到用户,则用户 www.a.com 默认访问北京服务器上面的缓存数据,实现就近访问的策略,大大提升了访问速度。

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

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

相关文章

CentOS6.8 安装node.js npm

环境:CentOS6.8_X64系统 一、到官方下载最新的编译好的安装文件,目前是6.9.4。 $>cd /usr/local/src #定位到这个目录,下载的文件会在这个目录#使用wget下载(这个内置命令) $>wget https://nodejs.org/dist/v8.1…

[上下界网络流][二分] Bzoj P2406 矩阵

题目描述 输入输出格式 输入格式: 第一行两个数n、m,表示矩阵的大小。 接下来n行,每行m列,描述矩阵A。 最后一行两个数L,R。 输出格式: 第一行,输出最小的答案; 输入输出样例 输入样…

记录自己的nest学习之旅

.a r 转载于:https://www.cnblogs.com/smzd/p/10978807.html

PYTHON 爬虫笔记七:Selenium库基础用法

知识点一:Selenium库详解及其基本使用 什么是Selenium selenium 是一套完整的web应用程序测试系统,包含了测试的录制(selenium IDE),编写及运行(Selenium Remote Control)和测试的并行处理(Sele…

pyqt5界面切换

#主要的思路就是创建两个frame(如果有两个以上同理)使用setVisible()函数显示或者隐藏frame 参数是bool值import sys from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import *class logindialog(QDialog):def __init__(sel…

mac 完全卸载vscode

原文分隔线while writing go this morning, I found that the wrong code are not under lined by red line This is really difficult for me and time consuming to keep writing. After 1 hour of wasting time trying to figure out what happened, I decide to kill it al…

RPC简介及框架选择

简单介绍RPC协议及常见框架,对比传统restful api和RPC方式的优缺点。常见RPC框架,gRPC及序列化方式Protobuf等 HTTP协议 http协议是基于tcp协议的,tcp协议是流式协议,包头部分可以通过多出的\r\n来分界,包体部分如何分…

CSS3的calc()使用

什么是calc()? 学习calc()之前,我们有必要先知道calc()是什么?只有知道了他是个什么东东?在实际运用中更好的使用他。 calc()从字面我们可以把他理解为一个函数function。其实calc是英文单词calculate(计算)的缩写,是css3的一个新…

typescript 类型映射 (ReadOnly、Partial)

有时候需要一个类型&#xff0c;是依赖于上一个类型但是&#xff0c;对属性的要求去不同interface Person{name: string;agent: number; } type Person2 Readonly<Person>; type Person3 Partial<Person>; class Test {run() {let person: Person {name: dd,age…

JAVA中几种常用的RPC框架介绍

RPC是远程过程调用的简称&#xff0c;广泛应用在大规模分布式应用中&#xff0c;作用是有助于系统的垂直拆分&#xff0c;使系统更易拓展。Java中的RPC框架比较多&#xff0c;各有特色&#xff0c;广泛使用的有RMI、Hessian、Dubbo等。RPC还有一个特点就是能够跨语言&#xff0…

C#中的多线程 - 同步基础

C#中的多线程 - 同步基础 C#中的多线程 - 同步基础 1同步概要在第 1 部分&#xff1a;基础知识中&#xff0c;我们描述了如何在线程上启动任务、配置线程以及双向传递数据。同时也说明了局部变量对于线程来说是私有的&#xff0c;以及引用是如何在线程之间共享&#xff0c;允许…

WC2019 自闭记

不咕了 Day 1 2019/1/24 辣么快就到冬令营了&#xff0c;还沉迷于被柿子吊打的状态的菜鸡一时半会还反应不过来。我们学校这次分头去的冬令营&#xff0c;差点上不了车。这次做的动车居然直达广州&#xff0c;强啊。 然鹅还是到太晚&#xff0c;没饭吃了。路上花了15大洋买了个…

v-slot vue2.6新增指令使用指南

子组件 <template><div class"wrapper"><slot name"demo" :msg"msg" text"this is a slot demo , ">this is demo slot.</slot></div> </template><script>export default {components: {…

跨语言RPC框架Thrift详解

一、 概念 Apache的Thrift软件框架&#xff0c;是用来进行可伸缩的、跨语言的服务开发&#xff0c;它通过一个代码生成引擎来构建高效、无缝的服务&#xff0c;这些服务能够实现跨语言调度&#xff0c;目前支持的语言有&#xff1a; C, Java, Python, PHP, Ruby, Erlang, Perl,…

小知识

1.时间格式的处理 new Date().format(yyyy-MM-dd hh:mm:ss) 2.保留两位小数的方法 element.recTime element.recTime.toFixed(2) 3.如何判断一个对象为空的方法 JSON.stringify(this.getEcho) ! "{}" 4.判断时间是否为标准格式的方法 (this.formValidate.outDateti…

增加标 和增加其内容

create table student( sno varchar(20) not null comment学号, sname varchar(20) not null comment学生姓名, ssex varchar(20) not null comment学生性别, sbirthday datetime comment学生出生年月, class varchar(20) comment 学生所在班级, primary key…

RPC服务和HTTP服务对比

很长时间以来都没有怎么好好搞清楚RPC&#xff08;即Remote Procedure Call&#xff0c;远程过程调用&#xff09;和HTTP调用的区别&#xff0c;不都是写一个服务然后在客户端调用么&#xff1f;这里请允许我迷之一笑~Naive&#xff01;本文简单地介绍一下两种形式的C/S架构&am…

MTK-TP(电阻屏校准程序ts_lib移植)

现今的项目中已经很少有使用电阻TP&#xff0c;但总有些奇怪的需求。如果项目中遇到需要校准电阻屏如何保证较快且较稳的调试TP呢。这里介绍使用ts_lib库来进行调试。 当然也可以使用一些常见的校准算法&#xff0c;采集5点&#xff0c;但最终的公式应该是不变的&#xff1a; X…

mac vscode 实用快捷键

cmddel:光标左边删到头 cmdfndel:光标右侧删到头转载于:https://www.cnblogs.com/smzd/p/11474488.html

ONENET读取与控制麒麟座MINI开发板LED状态

硬件 麒麟座MINI开发板V1.4 嵌入式软件 OneNET_Demo_ESP8266_EDP_Led 工程修改内容 led.c文件修改 函数LED_Init&#xff0c;mini开发板LED所在GPIO为PB6、PB7、PB8、PB9 函数LED_GetValue&#xff0c;mini开发板LED状态与IO口状态相反 /** * brief LED指示灯初始化函数**/v…