Java将数据放到缓存中,当需要从缓存中获取数据的时候获取不到?

我在项目中使用了如下代码,将一些数据放到了缓存中,当有地方需要调用getBAsset方法获取数据的时候,发现assetBuffer 中数据为空,这是什么原因呢?
当出现该问题的时候,我登录到项目部署的服务器上,查看服务器内存,发现可用内存只有100多M了,buffer内存占了3个G,服务器总内存为8个G,然后我把项目停了之后,将buffer内存清除之后,重新启动项目之后,再次调用getBAsset方法,assetBuffer是有数据的。(放入到缓存中的数据大概有16w左右)项目是用tomcat启动的,启动参数是这样配置的,给tomcat分了3G左右

image.png

想请问大佬们,为什么会出现getBAsset方法拿不到数据呢?是因为系统内存不足了,java内存中的数据被清空了?目前还暂不考虑加redis组件,感觉加了redis组件会解决此问题

/**
 * 缓存
 */
@Component
@Order(1)
@Slf4j
public class ScenarioBuffer implements IActionListener, ApplicationRunner {
    /**
     * 资产缓存
     * 系统启动时初始化,当资产增删改时,同步更新它;
     */
    private static Map<String, List<Asset>> assetBuffer = Collections.synchronizedMap(new HashMap<String, List<Asset>>());


    private static ScenarioBuffer instance = new ScenarioBuffer();

    public static ScenarioBuffer getInstance() {
        return instance;
    }

    /**
     * 从缓存中获取资产
     *
     * @param groupId
     * @return
     */
    public static List<Asset> getBAsset(String groupId) {
        if (assetBuffer.containsKey(groupId)) {
            return assetBuffer.get(groupId);
        }
        return null;
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        IAssetService assetService = SpringUtil.getBean(IAssetService.class);
        List<Asset> assetList = assetService.list();
        assetBuffer.put("key",assetList);
    }

}
阅读 867
avatarAI BotBETA

根据你提供的代码和描述,我无法确定问题的确切原因,但我可以给出一些可能的原因和解决方案。

  1. 内存不足问题:根据你描述的情况,当服务器可用内存较低时,可能发生了内存溢出或缓存被清理的情况。这可能会导致缓存的数据被清空或无法正确加载。当服务器内存紧张时,Java虚拟机(JVM)可能会对堆内存进行压缩,清除不必要的对象以释放空间,这也可能导致缓存数据被清除。

解决方案:你可以考虑优化服务器的内存使用,清理不必要的缓存或增加服务器的内存容量。此外,你可以尝试将缓存数据存储到磁盘上,而不是完全依赖于内存,以避免因内存不足而导致的数据丢失。

  1. 缓存同步问题:你的代码中使用了Collections.synchronizedMap来创建线程安全的Map,这意味着在多线程环境下,对assetBuffer的并发访问应该受到同步保护。但是,如果在缓存同步的过程中发生了并发修改或其他线程相关的问题,可能会导致数据不一致或获取不到正确的数据。

解决方案:确保在访问和修改缓存时进行正确的同步。对于assetBuffer的读写操作,你应该在适当的同步块或方法中进行,以避免并发修改和其他线程相关的问题。

  1. 缓存淘汰问题:虽然你的代码中使用了@Slf4j注解和log.error()来记录错误信息,但你没有提供具体的错误日志或异常信息。可能有其他异常或错误导致缓存被意外淘汰或清空。

解决方案:检查服务器的日志文件,查看是否有与缓存相关的错误或异常信息。这可能有助于确定问题的根本原因。

  1. 程序逻辑问题:除了上述可能的原因外,还有可能是程序逻辑错误或其他配置问题导致无法从缓存中获取正确的数据。

解决方案:进行逐步调试或添加适当的日志记录以跟踪程序执行流程。这有助于确定在哪个阶段出现了问题,并帮助你找到根本原因。

综上所述,以上是一些可能的原因和解决方案。你可以根据这些方向进行进一步的调查和调试,以找出问题的根本原因并采取适当的措施解决该问题。如果你能提供更多关于问题的具体细节或错误日志信息,我将能够提供更准确的帮助。

1 个回答

另外,你这类都使用@Component注解,Bean默认就是单例,getInstance()多此一举?

需要看下你在调用时怎么做的,理论上你最好使用@Resource之类注解进行依赖注入,而不是使用getInstance()这种方式。

既然是单例,就无需考虑多实例场景,故static也可省略。


另外,推挤你使用@PostConstruct或者InitializingBean,来完成一些Bean的业务类初始化动作。

既然使用Spring,就好好去用它


推荐你使用这种方式

@Component
public class ScenarioBuffer implements IActionListener {
    
    // 没必要使用 static
    // public static List<Asset> getBAsset(String groupId) {
    public List<Asset> getBAsset(String groupId) {
        if (assetBuffer.containsKey(groupId)) {
            return assetBuffer.get(groupId);
        }
        return null;
    }
}


@Service
public class XxxService {
    // 注入依赖
    @Resource
    private ScenarioBuffer scenarioBuffer;
    
    public void xxx() {
        // 直接使用即可
        final List<Asset> asset = scenarioBuffer.getBAsset("xxx");
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题