Web缓存方案

2020-04-02

Redis


数据库与业务服务器之间增设一个redis缓存服务器,客户端第一次请求的数据从数据库拿出后放到redis中,数据不过期或不更改的前提下,下次请求直接从redis中拿数据,缓解数据库压力。


内容分发网络 (CDN)

Content Delivery Network


数据缓存在各地的边缘服务器,通过中心平台的负载均衡、内容分发与调度,使用户就近获取所需内容,降低网络拥塞。


Http缓存


强缓存:不与服务器通信,直接使用本地资源

  • 根据Expires(资源过期的绝对时间) 来判断
    客户端修改本地时间后,缓存会错乱
  • 根据Cache-Control(资源过期的相对时间,即有效期长度) 来判断
    避免了客户端时间与服务端时间偏差带来的问题

两种方案可同时启用,同时启用时 Cache-Control 优先级更高

协商缓存:与服务器通信协商,是否使用本地资源

  • 根据Last-Modified/If-Modified-Since
    浏览器首次请求资源时,服务器返回 Last-Modified (资源最后修改时间)。浏览器再次请求该资源时,header中包含 If-Modified-Since,值为之前返回的 Last-Modified。服务器根据这个值判断是否命中缓存。
    这种方法不太准确,资源变化了最后修改时间也可以一致。
  • 根据Etag/If-None-Match
    Etag = H(资源编号, 资源最后修改时间, 资源大小)
    H:抗碰撞散列哈希,重复的概率非常小
    ETag 能够更加精准的控制缓存,保证每个资源是唯一的,资源的任何变化都会导致ETag变化。服务器根据浏览器发送的 If-None-Match 判断是否命中缓存。

两种方案可同时启用,同时启用时 ETag 优先级更高


IndexedDB


浏览器提供的本地数据库,允许存储大量数据、建立索引,可以被js创建和操作。
它有如下特点:

  1. 不属于关系型数据库,不支持SQL查询语句
  2. 数据以”键值对”的形式保存,每条数据记录都有对应的主键
  3. 异步
  4. 支持事务
  5. 同源限制
  6. 储存空间 > 250MB
  7. 支持二进制储存 (ArrayBuffer, Blob)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var db;

// 打开或创建数据库
function open() {
let request = window.indexedDB.open(name, version);

request.onsuccess = function (event) {
db = request.result;
console.log("打开成功");
};
request.onerror = function (event) {
console.log("打开失败");
};
}

// 新建表[person]
var store = db.createObjectStore('person', { keyPath: 'id' });
// 添加索引
store.createIndex('name', 'name', { unique: false });

// 新增数据
function add() {
let request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.add({ id: 1, name: '段誉'});

request.onsuccess = function (event) {
console.log('数据写入成功');
};
request.onerror = function (event) {
console.log('数据写入失败');
}
}



APP Cache


H5新增机制,通过manifest文件实现缓存,此法已废弃

1
<html manifest="index.appcache">
1
2
3
4
// 定义缓存清单 index.appache
CACHE:
index.html
script.js



Service Worker (SW)


是APP Cache的替代方案,在web Worker的基础上增加了离线缓存的能力。
它作为一个独立的线程来运作,可以拦截处理页面的所有网络请求(fetch),访问cache和indexedDB,支持服务端推送,让开发者自己管理缓存的版本。