【详解】高并发GuavaCache

举报
皮牙子抓饭 发表于 2025/07/18 21:33:53 2025/07/18
【摘要】 高并发GuavaCache在现代互联网应用中,高并发场景是每个开发者都可能遇到的挑战。为了提高系统的响应速度和吞吐量,缓存技术成为了一个不可或缺的部分。Google Guava库提供了一个强大的本地缓存实现——​​GuavaCache​​,它不仅简单易用,而且性能优秀,非常适合处理高并发场景。1. GuavaCache简介GuavaCache是Google Guava库中的一个组件,用于实现...

高并发GuavaCache

在现代互联网应用中,高并发场景是每个开发者都可能遇到的挑战。为了提高系统的响应速度和吞吐量,缓存技术成为了一个不可或缺的部分。Google Guava库提供了一个强大的本地缓存实现——​​GuavaCache​​,它不仅简单易用,而且性能优秀,非常适合处理高并发场景。

1. GuavaCache简介

GuavaCache是Google Guava库中的一个组件,用于实现内存中的缓存。它支持多种配置选项,如设置缓存大小、过期策略等,并且提供了线程安全的操作方法,使得在多线程环境中使用更加方便。

2. 主要特性

2.1 线程安全

GuavaCache的所有操作都是线程安全的,这使得它在高并发环境下能够稳定运行,无需额外的同步控制。

2.2 自动加载

可以通过​​LoadingCache​​接口实现数据的自动加载,当缓存中没有找到对应的键时,会自动调用指定的方法来加载数据。

2.3 过期策略

支持基于时间的过期策略,包括创建后过期(expire after write)和访问后过期(expire after access)。

2.4 内存回收

GuavaCache可以根据内存情况自动回收不常用的条目,避免内存溢出。

3. 使用示例

3.1 基本使用

首先,需要添加Guava库到项目中,如果使用Maven,可以在​​pom.xml​​中添加如下依赖:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

接下来,创建一个简单的缓存实例:

import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class GuavaCacheExample {
    public static void main(String[] args) throws ExecutionException {
        // 创建一个LoadingCache实例
        LoadingCache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(100) // 设置缓存的最大容量
                .expireAfterWrite(10, TimeUnit.MINUTES) // 设置过期时间为10分钟
                .build(new CacheLoader<String, String>() { // 定义默认的数据加载机制
                    @Override
                    public String load(String key) throws Exception {
                        return "value-" + key;
                    }
                });

        // 访问缓存
        String value = cache.get("key1");
        System.out.println(value); // 输出: value-key1
    }
}

3.2 异常处理

在实际应用中,数据加载可能会抛出异常。GuavaCache允许你定义如何处理这些异常:

try {
    String value = cache.get("key2");
} catch (ExecutionException e) {
    // 处理异常
    System.err.println("Failed to load value for key2: " + e.getCause());
}

3.3 手动加载和删除

除了自动加载外,还可以手动将数据放入缓存或从缓存中删除数据:

// 手动加载
cache.put("key3", "value3");

// 手动删除
cache.invalidate("key3");

4. 性能优化

4.1 并发级别

通过设置​​concurrencyLevel​​参数可以调整缓存的并发性能,这个值表示预计同时访问缓存的线程数。通常情况下,默认值已经足够好,但在特定场景下适当调整可以提升性能。

4.2 软引用与弱引用

对于内存敏感的应用,可以考虑使用软引用或弱引用来存储缓存项,这样当系统内存不足时,JVM会自动回收这些对象。

CacheBuilder.newBuilder()
    .softValues() // 使用软引用
    .weakKeys() // 使用弱引用
    .build();


GuavaCache是一个强大而灵活的缓存工具,特别适合于需要高性能和低延迟的应用。通过合理配置,可以有效应对高并发场景下的各种挑战。这篇文章介绍了GuavaCache的基本概念、主要特性和使用方法,以及一些性能优化的技巧,适合对缓存技术感兴趣的开发者阅读。Guava Cache 是一个非常高效的本地缓存库,特别适合处理高并发场景。下面是一个使用 Guava Cache 的示例代码,假设我们有一个需要频繁查询用户信息的应用场景。

场景描述

假设我们有一个用户服务,需要频繁地从数据库中查询用户信息。为了减少数据库的访问压力,我们可以使用 Guava Cache 来缓存用户信息。

依赖引入

首先,确保你的项目中已经引入了 Guava 库。如果你使用的是 Maven,可以在 ​​pom.xml​​ 中添加以下依赖:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>31.0.1-jre</version>
</dependency>

示例代码

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class UserCacheService {

    // 创建一个 Guava Cache 实例
    private final Cache<String, User> userCache;

    public UserCacheService() {
        // 配置缓存
        this.userCache = CacheBuilder.newBuilder()
                .maximumSize(1000) // 最大缓存条目数
                .expireAfterWrite(10, TimeUnit.MINUTES) // 缓存条目在写入后 10 分钟过期
                .recordStats() // 记录缓存统计信息
                .build();
    }

    // 获取用户信息
    public User getUser(String userId) {
        try {
            return userCache.get(userId, () -> loadUserFromDatabase(userId));
        } catch (ExecutionException e) {
            throw new RuntimeException("Failed to load user from cache", e);
        }
    }

    // 从数据库加载用户信息
    private User loadUserFromDatabase(String userId) {
        // 模拟从数据库加载用户信息
        System.out.println("Loading user " + userId + " from database");
        return new User(userId, "User Name " + userId);
    }

    public static void main(String[] args) {
        UserCacheService service = new UserCacheService();

        // 模拟高并发请求
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                User user = service.getUser("12345");
                System.out.println("User: " + user);
            }).start();
        }
    }
}

class User {
    private String id;
    private String name;

    public User(String id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{id='" + id + "', name='" + name + "'}";
    }
}

代码解释

  1. 缓存配置
  • ​maximumSize(1000)​​:设置缓存的最大条目数为 1000。
  • ​expireAfterWrite(10, TimeUnit.MINUTES)​​:设置缓存条目在写入后 10 分钟过期。
  • ​recordStats()​​:记录缓存的统计信息,方便监控和调试。
  1. 获取用户信息
  • ​getUser​​ 方法通过 ​​userCache.get​​ 方法从缓存中获取用户信息。如果缓存中没有该用户信息,则调用 ​​loadUserFromDatabase​​ 方法从数据库中加载用户信息,并将其存入缓存。
  1. 从数据库加载用户信息
  • ​loadUserFromDatabase​​ 方法模拟从数据库中加载用户信息的过程。
  1. 模拟高并发请求
  • 在 ​​main​​ 方法中,创建多个线程模拟高并发请求,每个线程都尝试获取同一个用户的用户信息。由于缓存的存在,多次请求只会触发一次数据库查询。

总结

通过使用 Guava Cache,我们可以有效地减少对数据库的访问次数,提高系统的性能和响应速度。特别是在高并发场景下,缓存的作用更加明显。希望这个示例对你有所帮助!在处理高并发场景时,缓存是提高系统性能和响应速度的重要手段之一。Google Guava库提供了一个非常强大的本地缓存实现——​​GuavaCache​​,它不仅提供了基本的缓存功能,还支持多种高级特性,如过期策略、大小限制、统计信息等,非常适合在高并发环境下使用。

1. 基本概念

  • Cache:Guava Cache的主要接口,用于定义缓存的基本操作,如获取、插入和删除缓存项。
  • LoadingCache:继承自​​Cache​​,提供了一种自动加载数据到缓存中的机制,当缓存中没有请求的数据时,可以自动从数据源加载。
  • RemovalListener:监听器接口,用于监听缓存项的移除事件,可以实现一些清理工作或日志记录。

2. 创建Guava Cache

创建一个简单的​​GuavaCache​​可以通过​​CacheBuilder​​来完成。以下是一个基本的例子:

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;

import java.util.concurrent.TimeUnit;

public class GuavaCacheExample {
    public static void main(String[] args) {
        // 创建一个最大容量为100,超过容量后使用LRU算法移除最近最少使用的条目,
        // 并且设置10分钟后过期的缓存
        Cache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(100)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .removalListener(notification -> System.out.println("Removed: " + notification.getKey()))
                .build();

        // 向缓存中添加数据
        cache.put("key1", "value1");

        // 从缓存中获取数据
        String value = cache.getIfPresent("key1");
        System.out.println(value); // 输出: value1
    }
}

3. 使用LoadingCache

​LoadingCache​​可以在缓存未命中时自动加载数据,这通常通过实现​​CacheLoader​​来完成:

import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class LoadingCacheExample {
    public static void main(String[] args) throws ExecutionException {
        LoadingCache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(100)
                .expireAfterWrite(10, TimeUnit.MINUTES)
                .build(new CacheLoader<String, String>() {
                    @Override
                    public String load(String key) throws Exception {
                        return fetchFromDatabase(key);
                    }
                });

        // 获取数据,如果缓存中没有,会自动调用load方法加载
        String value = cache.get("key1");
        System.out.println(value); // 输出: 从数据库获取的数据
    }

    private static String fetchFromDatabase(String key) {
        // 模拟从数据库查询
        return "从数据库获取的数据";
    }
}

4. 高级特性

  • 统计信息:通过​​cache.stats()​​可以获得缓存的统计信息,如命中率、加载失败次数等。
  • 异步加载:可以使用​​getUnchecked​​或​​getAll​​方法进行异步加载,适合于耗时较长的操作。
  • 刷新策略:通过​​refreshAfterWrite​​方法可以设置缓存项在写入后的多久时间后刷新。

5. 注意事项

  • 线程安全:Guava Cache是线程安全的,多线程环境下的读写操作不需要额外的同步控制。
  • 内存占用:虽然Guava Cache提供了多种策略来控制缓存大小,但在高并发场景下仍需注意内存使用情况,避免因内存溢出导致应用崩溃。
  • 过期策略:合理设置过期时间和清除策略,避免缓存中的数据长时间不更新,导致数据陈旧。

通过上述介绍,希望你能对Guava Cache在高并发场景下的使用有一个全面的了解。如果你有更具体的问题或需要进一步的帮助,请随时提问!

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。