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

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

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 参数的时间单

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

总结:

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

猜你喜欢

转载自blog.csdn.net/u010168160/article/details/52022726