如何使用才能让缓存更高效

Posted 小兀哥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用才能让缓存更高效相关的知识,希望对你有一定的参考价值。

      在大数据下,我们在追求性能的时候往往离不开缓存的使用,可是怎么使用缓存才能更高效呢?这一直是我们在追求解决的一个问题,今天我们就来介绍一种比较高效的使用方法。

1、代码展示

  • 缓存类
public class ConfigCache 

    private static final Logger                         log             = LoggerFactory
                                                                            .getLogger(ConfigCache.class);

    /** 科目缓存 */
    private static Map<String, Map<String, TitleDO>>    TITLE_MAP       = new HashMap<>();

    private static ScheduledExecutorService             executorService = Executors
                                                                            .newScheduledThreadPool(
                                                                                1,
                                                                                new NamedThreadFactory(
                                                                                    "bonus-config-cache",
                                                                                    true));


    /** 科目DAO */
    @Resource
    private TitleDAO                                    titleDAO;

    /**
     * 初始化,注入配置文件中启动时加载
     */
    public void init() 
        log.debug("load p-general config information!");
        reload();

        executorService.scheduleWithFixedDelay(new Runnable() 
            @Override
            public void run() 
                log.info("reload p-general config information!");
                try 
                    reload();
                 catch (Exception ex) 
                    log.warn("reload p-general config occurs exception, wait for next time");
                
            
        , 5, 5, TimeUnit.MINUTES);
    

    /**
     * 加载缓存
     */
    public void reload() 

        // 从数据中查出科目信息
        List<TitleDO> titleDOList = titleDAO.selectAll();
        HashSet<String> titleSet = new HashSet<>();
        for (TitleDO titleDO : titleDOList) 
            titleSet.add(titleDO.getReconInst());
        
        for (String str : titleSet) 

            Map<String, TitleDO> map = new HashMap<>();
            for (TitleDO titleDO : titleDOList) 
                if (StringUtils.equals(str, titleDO.getReconInst())) 
                    map.put(String.format("%s%s%s", titleDO.getTitleCode(), titleDO.getReconInst(),
                        titleDO.getLedgerType()), titleDO);
                

            
            TITLE_MAP.put(str, map);

        

    

    /**
     * 根据班级获取科目列表
     * 
     * @param reconInst 班级
     * @return 科目列表
     */
    public List<TitleDO> getTitleList(String reconInst) 

        Assert.notBlank(reconInst, "归属机构不能为空");
        List<TitleDO> list = new ArrayList<>();

        // 存在缓存直接取值
        if (TITLE_MAP.containsKey(reconInst)) 

            Map<String, TitleDO> map = TITLE_MAP.get(reconInst);
            Iterator<Entry<String, TitleDO>> it = map.entrySet().iterator();
            while (it.hasNext()) 
                list.add(it.next().getValue());
            
            return list;

        

        // 不存在缓存,去数据库查,然后放到缓存
        if (!TITLE_MAP.containsKey(reconInst)) 

            Map<String, String> condParam = new HashMap<String, String>();
            condParam.put("reconInst", reconInst);
            condParam.put("titleStatus", TitleStatusEnum.OPEN.getCode());
            list = titleDAO.selectListByCond(condParam);
            Map<String, TitleDO> map = new HashMap<>();
            for (TitleDO titleDO : list) 
                map.put(
                    String.format("%s%s%s", titleDO.getTitleCode(), titleDO.getReconInst(),
                        titleDO.getLedgerType()), titleDO);
            
            TITLE_MAP.put(reconInst, map);
        
        return list;
    
  • 使用
/** 缓存工具类 */
@Resource
private ConfigCache configCache;

public void test()
    TitleDO titleDO = null;
    String className="1";
    try 
        //根据科班级查询出科目信息
        titleDO = configCache.getTitleList(className);

     catch (Exception e) 
        log.info("configCache.getTitleList()--利用缓存根据班级查询出科目信息失败", e);
    

2、分析

      我们看代码,特别的地方就是有个单线程的定时任务。这样我们可以保证所需的数据在缓存里基本是能找到的,减少了数据库的访问次数,从而使性能更优。

scheduleWithFixedDelay
ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                          long initialDelay,
                                          long delay,
                                          TimeUnit unit)
//参数:
//command - 要执行的任务
//initialDelay - 首次执行的延迟时间
//delay - 一次执行终止和下一次执行开始之间的延迟
//unit - initialDelay 和 delay 参数的时间单

      此方法是创建并执行一个在给定初始延迟后首次启用的定期操作,随后,在每一次执行终止和下一次执行开始之间都存在给定的延迟。如果任务的任一执行遇到异常,就会取消后续执行。否则,只能通过执行程序的取消或终止方法来终止该任务。

总结:

      我们在性能优化的时候总是要考虑数据库的性能,因为在数据爆炸的这个年代,我们系统的瓶颈都在数据库。所以降低了数据库的损耗就会是性能得到很大提升。

以上是关于如何使用才能让缓存更高效的主要内容,如果未能解决你的问题,请参考以下文章

React:我怎样才能让这个 React 组件写得更好更高效?

三种沟通措施让你的团队运行更高效

如何才能让项目团队高效稳定?

iOS 如何高效的使用多线程

如何让 Python 中的 for 循环更高效

浪潮服务器构建Hadoop平台,让数据分析更高效