/mini_cache

一个用Java写的小型高性能缓存项目

Primary LanguageJava

mini_cache

项目概述:学习Java并发编程后,利用线程池、锁等J.U.C并发包中工具,从0到1逐步迭代写出一个小型缓存。

核心业务逻辑:用函数doCompute()模拟一个复杂计算,计算出的结果存入缓存,如在缓存有效期间再次输入相同计算条件,则直接返回缓存中的计算结果

说明:代码升级详情请见每次commit。

​ 虽经多次升级,但由于水平有限,本项目实属玩具类型缓存。

version1.0

  • 代码实现: 缓存功能粗浅地可以认为由Key查Value,若可以在缓存中查到,直接返回。否则查询数据库,并将结果写入缓存,因此最直接的想法就是用一个HashMap来作为缓存项目最底层的数据结构。并用sychronized保证线程安全(HashMap在多线程环境下进行put操作可能会引起死循环)
  • 明显缺陷:虽然最基础的功能是实现了,但是由于使用了synchronized导致查询操作同时刻最多只能有一个线程访问,和缓存的应用场景背道而驰,何不使用ConcurrentHashmap呢?

version1.1

  • 代码改进:使用ConcurrentHashmap初步解决了线程安全问题和性能问题。

  • 明显缺陷:重复计算问题。 经过测试发现,当到多个任务到达时间相近时,由于首次计算结果还未得出,导致即使后续有相同的计算任务,而又一次进入执行计算的代码,浪费了服务器资源。

version1.2

  • 代码改进:使用Future机制,用futuretask来存放异步计算的结果

  • 明显缺陷:如果后来的任务在第一个任务在futuretask还没有put进缓存时被调度执行,仍会发生重复计算的问题,虽然这个概率已经比上一个没有引入futuretask版本的降低了很多。

version1.3

  • 代码改进:使用原子操作彻底解决重复计算问题
  • 明显缺陷:模拟真实场景,如果由于某种原因计算失败,还需要重新计算

version1.4

  • 代码改进:设置50%的概率计算出错,抛出异常并重新计算,注意缓存污染问题,即发生错误要remove掉相应的值
  • 明显缺陷:未考虑缓存有效期问题

version1.5

  • 代码改进:利用ScheduledThreadPoolExecutor实现缓存的定期清除

test

  • 使用线程池测试缓存性能
  • 使用CountDownLatch模拟压测
  • 使用ThreadLocal确认时间的统一性

补充:版本1.0到1.1之间还实现了缓存和业务类(计算)的解耦