Redis+Caffeine 太强了!
对比一下之前的 “老古董” 本地缓存比如 Guava Cache,Caffeine 的性能直接碾压 —— 最新测试数据显示,在高并发场景下,Caffeine 的命中率比 Guava Cache 高 10%-20%,而且内存占用更省。我之前把项目里的 Guava Cache 换成 Caffeine,接口响应时间直接从 8ms 降到了 3ms,内存占用还少了 15%,简直是 “降维打击”。
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
兄弟们,咱先聊个扎心的事儿 —— 你是不是也遇到过这样的情况:线上接口明明加了 Redis 缓存,可高峰期还是慢得要死?或者本地缓存用得挺爽,一搞分布式部署就各种数据不一致,心态直接崩了?
我前阵子就踩过这坑:负责的商品详情接口,一开始只怼了 Redis,QPS 低的时候还挺稳,结果大促前压测,接口响应时间直接从 20ms 飙到 200ms,运维大哥天天追着我问 “是不是缓存没生效”。后来查了半天发现,不是 Redis 不行,是每次请求都要跨网络去捞 Redis 的数据,量大了之后,那网络开销就跟堵车似的,越积越慢。
直到我把 Redis 和 Caffeine 凑到一块儿,嘿,你猜怎么着?接口响应直接打回 10ms 以内,大促峰值也稳得一批。今天就跟大家好好唠唠,这俩 “缓存神器” 组队之后,到底有多强,以及咱们怎么在项目里把它们用明白 —— 全程大白话,没那么多绕人的术语,放心看!
一、先搞懂:Redis 和 Caffeine,各自到底啥本事?
在说 “组队” 之前,咱得先摸清这俩货的底细。就跟打游戏组队一样,你得知道辅助能加血、输出能秒人,才能配合好不是?
1. Redis:“远程仓库”,能存还能扛,但跑起来费点劲
Redis 这哥们儿,咱 Java 开发者基本都熟,号称 “内存数据库”,但咱平时用得最多的还是它的缓存功能。它的优点那是相当突出:
首先是 “能存”—— 不仅能存字符串,还能存哈希、列表、集合这些复杂结构,比如你想缓存用户的基本信息 + 订单列表,直接用哈希或者列表就能搞定,不用自己再拆数据。而且它支持持久化,就算 Redis 服务重启,之前缓存的数据也能找回来,不用怕 “一重启缓存全没了,数据库瞬间被打崩” 的尴尬。
然后是 “能扛”—— 分布式部署的时候,Redis 能搞集群,多台机器一起分担压力,比如你搞个 3 主 3 从的集群,QPS 轻松上 10 万,应对大部分业务场景都没问题。而且它是独立于应用服务的,不管你应用部署多少台机器,都能共享一份 Redis 缓存,不会出现 “每台应用都缓存一份,内存浪费还数据不一致” 的情况。
但 Redis 也有个明显的短板:它是 “远程缓存”,也就是说你的应用要拿数据,得通过网络请求去 Redis 服务器捞。这网络开销看着不大,比如一次请求就 1-2ms,但架不住请求多啊!比如你接口 QPS 是 1 万,那光网络开销就占了 1-2 万 ms 的总耗时,要是再遇到网络波动,延迟直接翻倍,接口响应时间可不就上去了?
举个实际的例子:我之前做的用户中心接口,每次查用户信息都要先调 Redis,在 QPS 5000 的时候,接口响应时间大概是 15ms,其中有 3ms 都是花在网络传输上。后来把 QPS 提到 1 万,网络延迟直接涨到 5ms,接口响应也跟着到了 20ms—— 别小看这几毫秒,在高并发场景下,这就是 “能用” 和 “好用” 的区别。
2. Caffeine:“桌面快捷方式”,秒回但内存有限
再说说 Caffeine,这玩意儿可能有些兄弟用得少,但它在本地缓存里绝对是 “天花板” 级别的存在。啥是本地缓存?简单说就是把数据存在你应用服务自己的内存里,拿数据的时候不用走网络,直接从内存里读,那速度叫一个快 —— 基本上是微秒级别的,比如一次读取只要 0.1ms,比 Redis 快了至少 10 倍。
Caffeine 的厉害之处,除了快,还有它的 “缓存淘汰算法”——W-TinyLFU 算法。咱不用纠结这个算法的具体原理,用大白话讲就是:它能聪明地判断哪些数据是 “常用的”,哪些是 “冷门的”,当缓存满了的时候,优先把冷门数据删掉,保留常用数据。
比如你做电商 ,首页的 “热门商品” 每天被访问几十万次,而某些 “小众商品” 可能几天才被访问一次。Caffeine 就会把 “热门商品” 留在缓存里,把 “小众商品” 淘汰掉,这样既能保证常用数据的访问速度,又不会让缓存占满应用的内存。
对比一下之前的 “老古董” 本地缓存比如 Guava Cache,Caffeine 的性能直接碾压 —— 最新测试数据显示,在高并发场景下,Caffeine 的命中率比 Guava Cache 高 10%-20%,而且内存占用更省。我之前把项目里的 Guava Cache 换成 Caffeine,接口响应时间直接从 8ms 降到了 3ms,内存占用还少了 15%,简直是 “降维打击”。
但 Caffeine 也有个致命缺点:它是 “本地缓存”,只能存在单个应用实例里。比如你把应用部署了 10 台机器,那每台机器都会有一份 Caffeine 缓存,这就会出现两个问题:
一是 “内存浪费”——10 台机器都缓存同一份数据,相当于重复存了 10 遍,要是数据量大,内存直接扛不住;
二是 “数据不一致”—— 比如你更新了商品价格,只更了其中一台机器的 Caffeine 缓存,其他 9 台还是旧数据,用户访问不同机器就会看到不同的价格,这锅你可背不起。
二、为啥要把 Redis 和 Caffeine 凑一起?1+1>2 的秘密
看完上面俩货的优缺点,你是不是已经想到了:既然 Redis 能分布式共享、持久化,但慢在网络;Caffeine 快如闪电,但只能本地存、易不一致 —— 那把它们俩结合起来,不就能互补了吗?
还真就是这么回事!Redis+Caffeine 的组合,本质上是 “双层缓存架构”:
第一层:本地 Caffeine 缓存,存 “高频访问” 的数据(比如首页热门商品、用户会话信息),拿数据的时候先查这里,秒级响应;第二层:远程 Redis 缓存,存 “中频访问” 或者 “需要分布式共享” 的数据(比如商品详情、用户订单),当 Caffeine 里没有的时候,再去 Redis 里捞;最底层:数据库,只存 “原始数据”,当 Redis 里也没有的时候,才去数据库里查,查完之后再把数据往 Redis 和 Caffeine 里存一份,下次就不用再查数据库了。这么一套组合拳打下来,好处可就太多了:
1. 速度快:大部分请求都被 Caffeine 拦住了
根据 “二八定律”,80% 的请求都是访问那 20% 的高频数据。比如电商 ,80% 的用户都是在看首页的热门商品,只有 20% 的用户会去看小众商品或者详情页。
要是只用 Redis,那 80% 的请求都要走网络去捞 Redis 的数据;但加了 Caffeine 之后,80% 的请求直接从本地内存里拿数据,根本不用碰网络,接口响应速度自然就上去了。
我之前做的商品首页接口,加 Caffeine 之前,平均响应时间是 18ms,其中 10ms 是网络开销;加了 Caffeine 之后,85% 的请求都命中 Caffeine,平均响应时间直接降到了 5ms,用户体验直接拉满。
2. 扛得住:Redis 压力大减,数据库更安全
既然 80% 的请求都被 Caffeine 拦住了,那打到 Redis 上的请求就只剩下 20% 了,Redis 的压力一下子就小了很多。比如之前 Redis 要扛 1 万 QPS,现在只需要扛 2000 QPS,就算遇到高峰期,也不容易出现 Redis 过载的情况。
而数据库就更安全了 —— 只有当 Caffeine 和 Redis 里都没有数据的时候,才会去查数据库,这种情况可能只占 1% 都不到。比如我之前做的订单查询接口,没加双层缓存的时候,数据库 QPS 高峰期能到 1000,加了之后直接降到 50,数据库再也没出现过 “连接超时” 的情况。
3. 数据稳:Redis 保证分布式一致性
虽然 Caffeine 是本地缓存,但我们可以通过 Redis 来保证分布式场景下的数据一致性。比如你更新了商品价格,流程可以是这样:
先更新数据库里的商品价格;然后删除 Redis 里对应的商品缓存(注意是删除,不是更新,避免并发问题);最后删除当前应用实例的 Caffeine 缓存。这样一来,下次有请求来的时候:
先查 Caffeine,发现没有,去查 Redis;Redis 里也没有,去查数据库,拿到最新的价格;把最新价格存到 Redis 和 Caffeine 里,后续的请求就能拿到正确的数据了。就算你部署了 10 台机器,只要每台机器在更新数据的时候,都删除自己的 Caffeine 缓存和 Redis 缓存,那所有机器后续都会从数据库里捞最新数据,不会出现数据不一致的情况。
三、实战:Spring Boot 项目里怎么集成 Redis+Caffeine?
光说不练假把式,接下来咱就手把手教大家,怎么在 Spring Boot 项目里把 Redis 和 Caffeine 集成起来,实现双层缓存。
1. 先搞依赖:把需要的 Jar 包引进来
首先,在 pom.xml 里加三个依赖:Spring Boot 的缓存 starter、Redis starter、Caffeine 的依赖。注意版本别太老,我这里用的是 Spring Boot 2.7.x 的版本,大家可以根据自己的项目版本调整。
2. 配置文件:告诉项目 Redis 和 Caffeine 在哪
然后在 application.yml 里加配置,主要是 Redis 的连接信息和 Caffeine 的缓存配置。
spring: # Redis配置 redis: host: 127.0.0.1 # 你的Redis地址,线上环境要填实际的IP port: 6379 # Redis端口,默认6379 password: 123456 # 你的Redis密码,没设的话可以去掉 lettuce: pool: max-active: 8 # 最大连接数 max-idle: 8 # 最大空闲连接数 min-idle: 2 # 最小空闲连接数 max-wait: 1000ms # 最大等待时间,超过这个时间就报错 # 缓存配置 cache: type: CAFFEINE # 默认缓存类型是Caffeine,后面我们会自定义双层缓存 caffeine: # Caffeine的缓存配置:初始容量100,最大容量1000,过期时间5分钟 initial-capacity: 100 maximum-size: 1000 expire-after-write: 5m
这里要注意:Caffeine 的配置要根据你的业务场景来调。比如 “初始容量” 可以设成你预估的常用数据量,避免频繁扩容;“最大容量” 不能设太大,不然会占满应用内存,比如你应用内存是 2G,那 Caffeine 最大容量别超过 5000(具体看每条数据的大小);“过期时间” 要看数据的更新频率,比如商品价格一天更一次,那过期时间可以设 1 天,要是实时性要求高,比如用户余额,那过期时间可以设 5 分钟。
3. 核心配置类:实现双层缓存逻辑
这一步是关键 —— 我们要自定义一个缓存管理器,让它同时支持 Caffeine 和 Redis,实现 “先查 Caffeine,再查 Redis,最后查数据库” 的逻辑。
首先,写一个 Redis 的配置类,主要是配置 RedisTemplate,避免默认的序列化问题(默认的 JdkSerializationRedisSerializer 会把数据序列化成乱码):
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.StringRedisSerializer;@Configurationpublic class RedisConfig { @Bean public RedisTemplate
然后,写一个双层缓存的配置类,自定义缓存管理器:
import com.github.ben-manes.caffeine.cache.Caffeine;import org.springframework.cache.Cache;import org.springframework.cache.CacheManager;import org.springframework.cache.caffeine.CaffeineCache;import org.springframework.cache.support.CompositeCacheManager;import org.springframework.cache.support.SimpleCacheManager;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCache;import org.springframework.data.redis.cache.RedisCacheConfiguration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.core.RedisTemplate;import java.time.Duration;import java.util.ArrayList;import java.util.List;@Configurationpublic class CacheConfig { // 1. 配置Caffeine缓存管理器 @Bean public CacheManager caffeineCacheManager() { SimpleCacheManager cacheManager = new SimpleCacheManager(); List
这里解释一下:CompositeCacheManager 是 Spring 提供的复合缓存管理器,它会按照你传入的缓存管理器顺序去查询 —— 先查 caffeineCacheManager,要是没命中,再查 redisCacheManager。这样就实现了 “先本地,再远程” 的双层缓存逻辑。而且我们可以针对不同的业务场景,配置不同的缓存(比如 hotProductCache、userSessionCache),每个缓存的初始容量、最大容量、过期时间都可以单独设置,非常灵活。
4. 业务代码:用 @Cacheable 注解实现缓存
配置完之后,业务代码就简单了 —— 只需要在需要缓存的方法上加 @Cacheable 注解,指定用哪个缓存就行。
比如我们写一个商品服务,查询热门商品的方法:
import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;@Servicepublic class ProductService { // 模拟从数据库查询商品信息 private Product getProductFromDb(Long productId) { // 这里实际项目中会调用DAO层查数据库,这里模拟一下 System.out.println("从数据库查询商品:" + productId); return new Product(productId, "iPhone 15", 5999.0); } /** * 查询热门商品信息 * @Cacheable:表示这个方法的返回值会被缓存 * value:指定用哪个缓存(对应我们之前配置的"hotProductCache") * key:缓存的Key,这里用商品ID作为Key,比如"hotProductCache:1" */ @Cacheable(value = "hotProductCache", key = "#productId") public Product getHotProduct(Long productId) { // 要是缓存没命中,就会执行下面的代码(查数据库) return getProductFromDb(productId); }}
再写一个 Controller,调用这个服务:
import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestControllerpublic class ProductController { @Resource private ProductService productService; @GetMapping("/product/hot/{productId}") public Product getHotProduct(@PathVariable Long productId) { long start = System.currentTimeMillis(); Product product = productService.getHotProduct(productId); long end = System.currentTimeMillis(); System.out.println("接口响应时间:" + (end - start) + "ms"); return product; }}
然后我们测试一下:
第一次访问http://localhost:8080/product/hot/1,控制台会打印 “从数据库查询商品:1” 和 “接口响应时间:20ms”(因为要查数据库);第二次访问同一个地址,控制台只会打印 “接口响应时间:1ms”(因为命中了 Caffeine 缓存,不用查数据库和 Redis);要是我们把应用重启,第一次访问会打印 “从数据库查询商品:1” 吗?不会!因为重启后 Caffeine 缓存没了,但 Redis 缓存还在,所以会先查 Caffeine(没命中),再查 Redis(命中),控制台会打印 “接口响应时间:5ms”,不用查数据库。你看,这样就完美实现了双层缓存的效果 —— 第一次查数据库,之后查 Caffeine,重启后查 Redis,全程不用频繁碰数据库,速度又快又稳。
四、进阶:解决 Redis+Caffeine 的那些 “坑”
虽然 Redis+Caffeine 很好用,但实际项目中还是会遇到一些问题,比如缓存穿透、缓存雪崩、数据不一致这些,要是不解决,分分钟出线上事故。接下来咱就聊聊这些 “坑” 怎么填。
1. 缓存穿透:请求查 “不存在的数据”,怎么办?
啥是缓存穿透?就是有人故意请求一个不存在的数据,比如查 productId=9999 的商品(数据库里根本没有),这样每次请求都会穿透 Caffeine 和 Redis,直接打到数据库上,要是请求多了,数据库直接就崩了。
怎么解决?有两个办法:
(1)缓存 “空值”
当数据库里没有这个数据的时候,我们也把 “空值” 存到 Caffeine 和 Redis 里,比如存一个 null 或者一个空对象,这样下次再查这个数据的时候,就会命中缓存,不会再查数据库了。
修改一下 ProductService 里的 getHotProduct 方法:
@Cacheable(value = "hotProductCache", key = "#productId", unless = "#result == null")public Product getHotProduct(Long productId) { Product product = getProductFromDb(productId); // 要是数据库里没有这个商品,返回一个空对象(不是null) if (product == null) { return new Product(productId, "", 0.0); } return product;}
这里的 unless = "#result== null" 表示:如果返回值是 null,就不缓存。所以我们返回一个空对象,这样就能把空对象缓存起来,下次再查的时候,就会命中缓存。
(2)布隆过滤器:提前拦截 “不存在的数据”
要是请求的 “不存在的数据” 太多,缓存空值会浪费 Redis 和 Caffeine 的内存,这时候就可以用布隆过滤器。布隆过滤器就像一个 “黑名单”,里面存了所有存在的 productId,当有请求来的时候,先过布隆过滤器:
要是布隆过滤器说 “这个 productId 不存在”,直接返回 404,不用查缓存和数据库;要是布隆过滤器说 “这个 productId 存在”,再走缓存和数据库的流程。Spring Boot 里集成布隆过滤器也很简单,用 Redisson 的布隆过滤器就行:
首先加 Redisson 依赖:
然后写一个布隆过滤器的配置类:
import org.redisson.api.RBloomFilter;import org.redisson.api.RedissonClient;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublicclass BloomFilterConfig { // 布隆过滤器的预期元素数量(比如有10000个商品) privatestaticfinallong EXPECTED_INSERTIONS = 10000; // 布隆过滤器的误判率(越小越准,但占用内存越大,一般设0.01) privatestaticfinaldouble FALSE_POSITIVE_RATE = 0.01; @Bean public RBloomFilter
然后修改 Controller 里的方法,先过布隆过滤器:
@GetMapping("/product/hot/{productId}")public Product getHotProduct(@PathVariable Long productId) { // 先查布隆过滤器,要是不存在,直接返回404 if (!productBloomFilter.contains(productId)) { throw new RuntimeException("商品不存在"); } long start = System.currentTimeMillis(); Product product = productService.getHotProduct(productId); long end = System.currentTimeMillis(); System.out.println("接口响应时间:" + (end - start) + "ms"); return product;}
这样一来,要是有人查 productId=10001 的商品,布隆过滤器直接拦截,不会再走缓存和数据库,完美解决缓存穿透问题。
2. 缓存雪崩:大量缓存同时过期,怎么办?
啥是缓存雪崩?就是你设置的缓存都在同一个时间点过期,比如你把所有商品缓存的过期时间都设成 1 小时,那 1 小时后,所有缓存都会过期,这时候大量请求会一下子全打到数据库上,数据库直接扛不住。
怎么解决?有两个办法:
(1)给过期时间加 “随机值”
不要让所有缓存都在同一个时间过期,比如在基础过期时间上再加一个 0-300 秒的随机值,这样缓存过期时间就分散了,不会出现 “同时过期” 的情况。
修改 CacheConfig 里的 Caffeine 缓存配置:
// 示例1:商品热门缓存,过期时间5分钟+随机0-300秒caches.add(new CaffeineCache("hotProductCache", Caffeine.newBuilder() .initialCapacity(100) .maximumSize(1000) .expireAfterWrite(Duration.ofMinutes(5).plus(Duration.ofSeconds((long) (Math.random() * 300)))) .build()));
Redis 的过期时间也一样,修改 RedisCacheConfiguration:
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() // 过期时间1小时+随机0-300秒 .entryTtl(Duration.ofHours(1).plus(Duration.ofSeconds((long) (Math.random() * 300)))) .prefixCacheNameWith("cache:") .serializeKeysWith(RedisCacheConfiguration.defaultCacheConfig().getKeySerializationPair()) .serializeValuesWith(RedisCacheConfiguration.defaultCacheConfig().getValueSerializationPair());
这样一来,每个缓存的过期时间都不一样,就不会出现大量缓存同时过期的情况了。
(2)Redis 集群:避免 Redis 单点故障
要是 Redis 服务器挂了,那所有依赖 Redis 的请求都会打到数据库上,也会造成 “雪崩”。所以线上环境一定要搞 Redis 集群,比如 3 主 3 从,就算其中一台主节点挂了,从节点会自动顶上,保证 Redis 服务不中断。
3. 数据不一致:更新数据后,缓存没同步,怎么办?
这个问题我们之前提过一嘴,就是更新数据库后,要及时删除对应的缓存,避免缓存里存的是旧数据。但实际项目中,可能会遇到 “并发更新” 的问题,比如:
线程 A 查询商品 1,缓存没命中,去查数据库,拿到旧价格 5999;线程 B 更新商品 1 的价格,改成 6999,然后删除了缓存;线程 A 查完数据库,把旧价格 5999 又存到缓存里;之后的请求查缓存,拿到的都是旧价格 5999,出现数据不一致。怎么解决?有两个办法:
(1)“更新数据库→删除缓存” 改成 “删除缓存→更新数据库”
先删除缓存,再更新数据库,这样就算有线程在更新前查询,也会因为缓存被删除,去查数据库,拿到的是最新的数据。
修改一下更新商品的方法:
import org.springframework.cache.annotation.CacheEvict;import org.springframework.stereotype.Service;@Servicepublicclass ProductService { // 模拟更新数据库里的商品信息 private void updateProductInDb(Product product) { System.out.println("更新数据库商品:" + product.getId() + ",新价格:" + product.getPrice()); } /** * 更新商品信息 * @CacheEvict:表示更新后删除对应的缓存 * value:要删除的缓存名称 * key:要删除的缓存Key */ @CacheEvict(value = "hotProductCache", key = "#product.id") public void updateProduct(Product product) { // 1. 先删除缓存 // (@CacheEvict注解会帮我们做这件事) // 2. 再更新数据库 updateProductInDb(product); // 3. 再删除Redis里的缓存(因为@CacheEvict默认只删除Caffeine缓存) redisTemplate.delete("cache:hotProductCache:" + product.getId()); }}
这里要注意:@CacheEvict 注解默认只会删除 Caffeine 缓存,所以我们还要手动删除 Redis 里的缓存,保证两者都被删除。
(2)加互斥锁:避免并发更新导致的问题
要是并发量特别大,就算先删除缓存再更新数据库,还是可能出现问题,这时候就可以加互斥锁,比如用 Redis 的 SETNX 命令(只有当 Key 不存在的时候才能设置成功),保证同一时间只有一个线程能更新商品。
修改 updateProduct 方法:
public void updateProduct(Product product) { String lockKey = "lock:product:" + product.getId(); // 加互斥锁,过期时间5秒,避免死锁 Boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", Duration.ofSeconds(5)); if (Boolean.TRUE.equals(locked)) { try { // 1. 删除Caffeine缓存 caffeineCacheManager.getCache("hotProductCache").evict(product.getId()); // 2. 删除Redis缓存 redisTemplate.delete("cache:hotProductCache:" + product.getId()); // 3. 更新数据库 updateProductInDb(product); } finally { // 释放锁 redisTemplate.delete(lockKey); } } else { // 没拿到锁,重试(可以用循环重试,或者返回失败让前端重试) thrownew RuntimeException("更新太频繁,请稍后再试"); }}
这样一来,同一时间只有一个线程能更新商品,就不会出现 “线程 A 存旧数据” 的问题了。
五、总结:Redis+Caffeine,该用在哪些场景?
聊了这么多,最后咱总结一下,Redis+Caffeine 的双层缓存架构,到底适合哪些场景:
高并发、低延迟要求的场景:比如电商首页、秒杀活动、直播带货,这些场景 QPS 高,用户对响应时间敏感,用双层缓存能把响应时间压到 10ms 以内;数据访问频率差异大的场景:比如大部分请求访问高频数据,少部分请求访问低频数据,用 Caffeine 存高频数据,Redis 存低频数据,既能保证速度,又能节省内存;分布式部署的场景:比如应用部署多台机器,需要共享缓存数据,用 Redis 保证分布式一致性,用 Caffeine 提升单机访问速度。当然,也不是所有场景都适合用双层缓存。比如数据实时性要求极高的场景(比如股票行情、实时订单数),缓存过期时间要设得很短,甚至不用缓存,直接查数据库;或者数据访问频率很低的场景(比如后台管理系统),用单 Redis 缓存就够了,没必要加 Caffeine。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
极客湾直播回应大横评下架事件!揭秘真相
极客湾直播回应横评视频下架:澄清非厂商施压,属个人行为导致 近期,头部科技评测频道“极客湾”发布的一期大型硬件横评内容突然从平台下架,迅速引发数码爱好者及行业内的广泛关注与猜测。一时间,舆论场上出现了多种解读,其中“多家厂商联合施压要求撤稿”的说法流传甚广。为此,极客湾核心成员云飞在最新直播中正面回
NVIDIA下代Rubin Ultra大调整!规格直接腰斩:放弃四芯封装转向双芯
NVIDIA下一代数据中心GPU Rubin Ultra确认重大设计调整:为何转向双芯片方案? 据最新产业消息,NVIDIA数据中心GPU的下一代旗舰产品Rubin Ultra,在关键设计上已完成路线图调整。其最大变化在于:产品放弃了此前规划的四颗GPU芯片(四芯片封装)方案,转而采用更为成熟可靠的
技嘉 AI TOP ATOM 登陆京东,携手趋境科技打造“开箱即用”本地AI超算
技嘉AI TOP ATOM与趋境科技完成联合调试,打造开箱即用的本地AI方案 近日,业界传来重要进展:技嘉面向AI开发者及小团队的桌面级AI超算产品——AI TOP ATOM,已与趋境科技完成针对本地大模型部署的深度联合调试。此次合作的核心,是将趋境科技自主研发的AMaaS(AI Model as
某厂骁龙 8E5 影像旗舰 SKU 曝光:最高 1TB 版本,预计为 OPPO Find X9 Ultra
某厂骁龙 8E5 影像旗舰 SKU 泄露,顶配 1TB 存储,锁定 OPPO Find X9 Ultra 下一代旗舰手机的传闻持续升温。今日,数码圈知名爆料人 @数码闲聊站 释放出关键信息,揭示了某头部品牌正在筹备中的骁龙 8E5 影像旗舰详细规格。综合配置分析与品牌产品迭代路径判断,这款即将登场的
DDR5内存数月来首次大降价!幕后推手曝光
持续高涨的DDR5内存行情首次降温,终端价格出现显著回调 近日市场监测数据显示,持续数月走高的DDR5内存价格终于迎来转折点,呈现近期首次明显回落趋势。根据北美多家主流零售渠道的报价信息,多款DDR5内存套装价格出现不同程度下调,部分型号降幅甚至高达100美元。值得注意的是,此轮价格调整尚属局部性调
- 日榜
- 周榜
- 月榜
相关攻略
2015-03-10 11:25
2015-03-10 11:05
2021-08-04 13:30
2015-03-10 11:22
2015-03-10 12:39
2022-05-16 18:57
2025-05-23 13:43
2025-05-23 14:01
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

