IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

一个cache的改造过程

淘宝数据平台团队 2010-10-18 08:11:21 累计浏览 3,628 次
本机暂存

在分布式的程序中,cache的合理使用可以带来性能上的极大提升,尤其是在资源创建需要昂贵的开销时。cache的设计最重要的是要保证线程安全和高效性。下面以代码为例,介绍了三种cache的写法。

1. 粗放的加锁

以下是代码片段:
public class Cache1 {
    private HashMap<String, ServerGroup> route2SG = null;

    public Cache1() {
        route2SG = new HashMap<String, ServerGroup>();
    }

    public synchronized ServerGroup get(String routeKey) throws IOException {
        ServerGroup sg = null;
        sg = route2SG.get(routeKey);
        if (sg == null) {
            sg = getServerGroup(routeKey);
            route2SG.put(routeKey, sg);
        }
        return sg;
    }

    public synchronized void remove(String routeKey) {
        route2SG.remove(routeKey);
    }

    private ServerGroup getServerGroup(String routeKey) throws IOException {
        ServerGroup sg = null;
        /**
         * Construct ServerGroup here
         */
        return sg;
    }
}

2. 读写锁

以下是代码片段:
public class Cache2 {
    private ConcurrentHashMap<String, ServerGroup> route2SG = null;
    private final ReadWriteLock lock = new ReentrantReadWriteLock();

    public Cache2() {
        route2SG = new ConcurrentHashMap<String, ServerGroup>();
    }

    public ServerGroup get(String routeKey) throws IOException {
        ServerGroup sg = null;
        try {
            lock.readLock().lock();
            sg = route2SG.get(routeKey);
            if (sg == null) {
                lock.readLock().unlock();
                lock.writeLock().lock();
                sg = route2SG.get(routeKey);
                if (sg == null) {
                    sg = getServerGroup(routeKey);
                    route2SG.put(routeKey, sg);
                }
                lock.readLock().lock();
                lock.writeLock().unlock();
            }
        } catch (IOException e) {
            lock.writeLock().unlock();
            throw (e);
        }
        lock.readLock().unlock();
        return sg;
    }

    public void remove(String routeKey) {
        try {
            lock.writeLock().lock();
            route2SG.remove(routeKey);
        } finally {
            lock.writeLock().unlock();
        }
    }

    private ServerGroup getServerGroup(String routeKey) throws IOException {
        ServerGroup sg = null;
        /**
         * Construct ServerGroup here
         */
        return sg;
    }
}

3. 无锁

以下是代码片段:
public class Cache3 {
    private ConcurrentHashMap<String, FutureTask<ServerGroup>> route2SGFT = null;

    public Cache3() {
        route2SGFT = new ConcurrentHashMap<String, FutureTask<ServerGroup>>();
    }

    public ServerGroup get(String routeKey) throws IOException, InterruptedException, ExecutionException {
        FutureTask<ServerGroup> ft = route2SGFT.get(routeKey);
        if (ft != null) {
            return ft.get();
        }
        FutureTask<ServerGroup> sft = new FutureTask<ServerGroup>(new ConstructSGTask(routeKey));
        FutureTask<ServerGroup> old = route2SGFT.putIfAbsent(routeKey, sft);
        if (old == null) {
            sft.run();
        }
        return sft.get();
    }

    public void remove(String routeKey) {
        route2SGFT.remove(routeKey);
    }

    class ConstructSGTask implements Callable<ServerGroup> {
        private final String key;

        public ConstructSGTask(String key) {
            super();
            this.key = key;
        }

        @Override
        public ServerGroup call() throws Exception {
            return getServerGroup(key);
        }

    }

    private ServerGroup getServerGroup(String routeKey) throws IOException {
        ServerGroup sg = null;
        /**
         * Construct ServerGroup here
         */
        return sg;
    }

}

总结,

从三份代码中可以看出,锁的粒度从粗放到无,这个就极大的提高了cache的并发性。

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. SmartSprites - 命令行形式的CSS Sprites生成器 (累计阅读 123,895)
  2. 一种常见的并发编程场景的处理 (累计阅读 23,590)
  3. Java开发岗位面试题归类汇总 (累计阅读 22,157)
  4. android 开发入门 (累计阅读 19,529)
  5. 浅析http协议、cookies和session机制、浏览器缓存 (累计阅读 17,446)
  6. 无锁消息队列 (累计阅读 14,276)
  7. 我的PHP,Python和Ruby之路 (累计阅读 13,149)
  8. HashMap解决hash冲突的方法 (累计阅读 12,654)
  9. Zookeeper工作原理 (累计阅读 12,203)
  10. 一种高效无锁内存队列的实现 (累计阅读 12,097)