缓存 封面
Vapor 大型教程

缓存

缓存能让接口变快、少调外部 API。本文介绍 Vapor 3 的 KeyedCache 协议,以及内存缓存、数据库/Redis 缓存各自适合什么场景。

一、KeyedCache 协议

Vapor 定义了 KeyedCache 协议,用来描述各种缓存机制需要满足的功能。它本身定义得很简单,只规定了「按 key 读写、删除」这三种能力:

public protocol KeyedCache {

    func get<D>(_ key: String, as decodable: D.Type) -> Future<D?> where D: Decodable

    func set<E>(_ key: String, to encodable: E) -> Future<Void> where E: Encodable

    func remove(_ key: String) -> Future<Void>
}

无论底层是内存、数据库还是 Redis,只要遵循这个协议,上层用法都是一致的:get 取值、set 存值、remove 删除。

二、内存缓存

内存缓存把数据存放在程序运行时分配的内存空间中。因为没有外部依赖,这种缓存非常适合在开发和测试阶段使用。不足之处在于:一旦程序结束,内存中的缓存数据就丢失了,而且不能在多个应用实例之间共用。

MemoryKeyedCache 可以在应用的所有事件循环(EventLoop)之间公用——也就是说,一旦有数据被缓存,所有事件循环都能访问它,非常利于开发和测试阶段。但这种方式不是线程安全的,要求同步访问,因此在生产环境下异步访问这些内存缓存数据可能存在问题。

DictionaryKeyedCache 只对当前事件循环自己有效,不同的事件循环各有自己的 Dictionary 缓存,所以一次会话中不同请求之间不能共用这种缓存。它适用于生产环境下的缓存。

三、数据库缓存

所有的数据库都可以用来做缓存,适用于「应用重启后」或「多个应用实例之间」需要共用缓存数据的情况。可以使用主数据库来缓存,也可以专门开辟一个数据库来缓存,常用的有 Redis 数据库缓存。

Redis 是一种开源缓存服务,能作为 Web 应用的缓存数据库,并被多数云服务商支持。它易于配置、快速、特性丰富。

构建 Web 应用时,向其它 API 请求数据可能造成延时;如果对方很慢,你自己接口的响应也会变慢。另外,其它 API 可能做了流量限制,一段时间内不能超过最大访问次数。有了缓存,就能减少访问这些外部 API 的次数,让你的接口响应更快速。

在计算机科学中,缓存是很重要的概念。存储 Web 应用缓存数据有几种方式:内存、Fluent 数据库、Redis 等。不同的缓存方式有不同的失效策略:LRU(Least Recently Used,最近最少使用)、RR(Random Replacement,随机替换)、LIFO(Last In First Out,后进先出)。

怎么选:开发/测试图省事用 MemoryKeyedCache;生产环境要跨实例共享、追求性能,就上 Redis;简单场景用 Fluent 数据库缓存也能凑合。选哪种,取决于你的部署形态和一致性要求。

本系列其他文章