提升接口性能之缓存
- 软件开发
- 2025-09-02 17:36:02

缓存策略: 从本地到分布式, 再到 HTTP 缓存的全面解析 引言
在当今的软件开发中, 缓存技术扮演着至关重要的角色. 它能够显著提升系统性能, 降低数据库负载, 提高用户体验. 本文将详细介绍三种常见的缓存策略: 本地缓存, 分布式缓存以及 HTTP 缓存, 并探讨如何在实际应用中合理运用它们.
一, 本地缓存 1.1 CaffeineCaffeine 是一个基于 Java 8 的高性能本地缓存库. 它结合了多种优秀的缓存算法, 具有极高的性能和可扩展性.
1.1.1 引入依赖在 Maven 项目中, 只需添加以下依赖:
<dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> <version>2.9.3</version> </dependency> 1.1.2 使用示例 import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; import java.util.concurrent.TimeUnit; public class CaffeineExample { public static void main (String [] args) { Cache<String, String> cache = Caffeine.newBuilder () .expireAfterWrite (10, TimeUnit.MINUTES) .maximumSize (100) .build (); cache.put ("key1", "value1"); String value = cache.getIfPresent ("key1"); System.out.println (value); } }在上述代码中, 我们设置了缓存项在写入 10 分钟后过期, 并设置了最大缓存容量为 100. 当缓存达到最大容量时, 会根据 LRU (最近最少使用) 策略淘汰旧的缓存项.
1.2 Guava CacheGuava Cache 是 Google Guava 库中的一部分, 提供了功能强大的本地缓存实现.
1.2.1 引入依赖 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.1-jre</version> </dependency> 1.2.2 使用示例 import com.google mon.cache.Cache; import com.google mon.cache.CacheBuilder; import java.util.concurrent.TimeUnit; public class GuavaCacheExample { public static void main (String [] args) { Cache<String, String> cache = CacheBuilder.newBuilder () .expireAfterWrite (5, TimeUnit.MINUTES) .maximumSize (50) .build (); cache.put ("key2", "value2"); String value = cache.getIfPresent ("key2"); System.out.println (value); } }这里同样设置了缓存项在写入 5 分钟后过期, 最大缓存容量为 50, 同样采用 LRU 淘汰策略.
二, 分布式缓存 2.1 RedisRedis 是一个开源的, 基于内存的数据结构存储系统, 常用作分布式缓存. 它支持多种数据结构, 如字符串, 哈希表, 列表等, 并且具有高可用性和高性能.
2.1.1 缓存预热在系统启动时, 可以通过编写脚本将热点数据提前加载到 Redis 中. 例如, 使用 Python 的 redis - py 库:
import redis r = redis.StrictRedis (host='localhost', port=6379, db = 0) # 假设热点数据存储在一个列表中 hot_data = [('key3', 'value3'), ('key4', 'value4')] for key, value in hot_data: r.set (key, value) 2.1.2 防雪崩策略为了防止大量缓存同时过期导致数据库压力瞬间增大, 可以为每个缓存项设置随机的过期时间. 例如, 在 Java 中使用 Jedis 操作 Redis:
import redis.clients.jedis.Jedis; import java.util.Random; public class RedisAntiAvalancheExample { public static void main (String [] args) { Jedis jedis = new Jedis ("localhost", 6379); Random random = new Random (); int baseExpireTime = 3600; // 基础过期时间 1 小时 int maxRandomOffset = 600; // 最大随机偏移 10 分钟 for (int i = 0; i < 10; i++) { String key = "key" + i; String value = "value" + i; int expireTime = baseExpireTime + random.nextInt (maxRandomOffset); jedis.setex (key, expireTime, value); } jedis.close (); } } 2.2 MemcachedMemcached 是一个高性能的分布式内存对象缓存系统, 主要用于动态 Web 应用以减轻数据库负载. 它的使用方式与 Redis 类似, 但数据结构相对简单, 主要以键值对形式存储.
2.2.1 缓存预热在 Python 中, 可以使用 pymemcache 库进行缓存预热:
from pymemcache.client import base client = base.Client (('localhost', 11211)) hot_data = [('key5', 'value5'), ('key6', 'value6')] for key, value in hot_data: client.set (key, value) 2.2.2 防雪崩策略在 Java 中使用 XMemcached 设置随机过期时间:
import net.rubyeye.xmemcached.MemcachedClient; import net.rubyeye.xmemcached.MemcachedClientBuilder; import net.rubyeye.xmemcached.XMemcachedClientBuilder; import net.rubyeye.xmemcached.utils.AddrUtil; import java.util.Random; public class MemcachedAntiAvalancheExample { public static void main (String [] args) throws Exception { MemcachedClientBuilder builder = new XMemcachedClientBuilder (AddrUtil.getAddresses ("localhost:11211")); MemcachedClient client = builder.build (); Random random = new Random (); int baseExpireTime = 3600; int maxRandomOffset = 600; for (int i = 0; i < 10; i++) { String key = "key" + i; String value = "value" + i; int expireTime = baseExpireTime + random.nextInt (maxRandomOffset); client.set (key, expireTime, value); } client.shutdown (); } } 三, HTTP 缓存 3.1 Cache - ControlCache - Control 是 HTTP/1.1 中用于控制缓存的通用首部字段. 通过设置不同的指令, 可以精确控制缓存行为.
3.1.1 示例在 Java 的 Spring Boot 项目中, 可以通过如下方式设置 Cache - Control 头:
import org.springframework.http.CacheControl; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.TimeUnit; @RestController public class HttpCacheExample { @GetMapping ("/staticResource") public ResponseEntity<String> getStaticResource () { CacheControl cacheControl = CacheControl.maxAge (3600, TimeUnit.SECONDS).cachePublic (); return ResponseEntity.ok () .cacheControl (cacheControl) .body ("This is a static resource"); } }上述代码设置了缓存有效期为 1 小时, 并且允许公共缓存 (如 CDN) 缓存该资源.
3.2 ETagETag (实体标签) 是一种用于缓存验证的机制. 服务器为每个资源生成一个唯一的标识符, 客户端在后续请求中携带该标识符, 服务器通过比较标识符来判断资源是否发生变化.
3.2.1 示例在 Java 的 Servlet 中, 可以如下生成和验证 ETag:
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @WebServlet ("/etagResource") public class ETagServlet extends HttpServlet { @Override protected void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String resource = "This is a resource with ETag"; String etag = generateETag (resource); String ifNoneMatch = request.getHeader ("If - None - Match"); if (ifNoneMatch!= null && ifNoneMatch.equals (etag)) { response.setStatus (HttpServletResponse.SC_NOT_MODIFIED); return; } response.setHeader ("ETag", etag); PrintWriter out = response.getWriter (); out.println (resource); } private String generateETag (String resource) { try { MessageDigest digest = MessageDigest.getInstance ("MD5"); byte [] hash = digest.digest (resource.getBytes ()); StringBuilder hexString = new StringBuilder (); for (byte b : hash) { hexString.append (String.format ("%02x", b)); } return hexString.toString (); } catch (NoSuchAlgorithmException e) { throw new RuntimeException (e); } } } 四, 总结本地缓存适用于减少单个应用内的重复计算和数据库查询, Caffeine 和 Guava Cache 提供了便捷的实现方式. 分布式缓存如 Redis 和 Memcached 则用于缓存全局共享数据, 通过缓存预热和防雪崩策略能有效降低数据库压力. HTTP 缓存则通过控制客户端和 CDN 对静态资源的缓存, 进一步提升了用户访问速度. 合理运用这三种缓存策略, 可以构建出高性能, 高可用的应用系统.