Java | 从本地缓存到分布式缓存

本文档中部分代码不保证可以运行

虽然标题为缓存,但在这里不仅仅会涉及缓存,还会涉及一些其他提高应用性能的方案。

在程序设计中,经常能听到的就是以时间换空间以空间换时间缓存作为一种能加快程序性能的银弹,它是典型的后者(以空间换时间).

随着用户数和访问量越来越大,我们的应用需要支撑更多的并发量,同时我们的应用服务器和数据库服务器所做的计算也越来越多。但是往往我们的应用服务器资源是有限的,数据库每秒能接受的请求次数也是有限的(或者文件的读写也是有限的),如何能够有效利用有限的资源来提供尽可能大的吞吐量?一个有效的办法就是引入缓存,每个环节中请求可以从缓存中直接获取目标数据并返回,从而减少计算量,有效提升响应速度,让有限的资源服务更多的用户。

缓存并不是包治百病的银弹

第一次接触缓存MAP

我第一次接触缓存的时候是在大三开始出去工作的时候。在一个系统中,基本每个接口都有可能要获取一次用户信息和一些用户配置,当时我们的系统查多改少,这也注定缓存可以大大提高我们的性能,当时的做法是维护一个全局的单例的Map作为缓存存储.记得当时的类名叫DBMirror

大致如下:

class DBMirror {
    private static Map<String, User> userCache = new HashMap<>();

    public static void putUser(String key, User user) {
        userCache.put(key, user);
    }

    public static User getUser(String key) {
        return userCache.get(key);
    } 

    private DBMirror() {}

}

代码很简单,基本满足了当时系统的要求,减少了很多数据库读写操作,在当时也是第一次开始意识到 数据库 并不是唯一的存储. 原来 Map 还能这样使用

但是上面的代码有个很大的缺点,随着用户的增多,里面并没有合适的剔除算法,会导致 Map 越来越大,极端情况会导致内存溢出

常见淘汰策略

如上所述,如果不使用剔除算法,会导致内存占用越来越大,且无法回收,那下面讲一下常见的淘汰策略

FIFO(first in first out)

先进先出策略,最先进入缓存的数据在缓存空间不够的情况下(超出最大元素限制)会被优先被清除掉,以腾出新的空间接受新的数据。

LFU(less frequently used)

最少使用策略,根据元素的被使用次数判断,清除使用次数较少的元素释放空间。

LRU(least recently used)

最近使用策略,根据元素最后一次被使用的时间戳,清除最远使用时间戳的元素释放空间。

其他

  1. 为缓存元素设置过期时间,清理超过过时时间的元素
  2. 随机清理
  3. 优先清理大对象

缓存简单分类

本地缓存:指的是在应用中的缓存组件,其最大的优点是应用和cache是在同一个进程内部,请求缓存非常快速,没有过多的网络开销等,在单应用不需要集群支持或者集群情况下各节点无需互相通知的场景下使用本地缓存较合适;同时,它的缺点也是应为缓存跟应用程序耦合,多个应用程序无法直接的共享缓存,各应用或集群的各节点都需要维护自己的单独缓存,对内存是一种浪费。

分布式缓存:指的是与应用分离的缓存组件或服务,其最大的优点是自身就是一个独立的应用,与本地应用隔离,多个应用可直接的共享缓存。缺点是:优点也就是缺点,因为自身是一个独立的应用,本地节点都需要与其进行通信,导致依赖网络,同时如果缓存服务崩溃可能会影响所有依赖节点

对于一些单个实例的服务,或者数据基本不会变化的数据都可以使用本地缓存来提高性能,反之可以使用分布式缓存

技术方案本身没有最好的,只有最合适的.

缓存的使用

Java集合类

在上面提供了一个简单的例子,DBMirror使用Map来时间一个简单的内存缓存,同时SetList都可以达到内存缓存的功能,根据并发情况可以选择不同的实现类,例如HashMapLinkedHashMapTreeMapLinkedTreeMapConcurrentHashMap... 总有一个满足你

这样实现很简单,但是也致命缺点:无法回收不常用的缓存

Guava Cache

说起 Guava, 很多人都不会陌生,它是 Google 提供的一个非常好用的 Java 工具包。Guava Cache 是 Guava 中的一个本地缓存实现,基于LRU算法实现,并提供了多种缓存过期策略,过期时间、容量等. 简化了缓存的使用,方便我们更加大胆的使用缓存

Caffeine

Caffeine是一个基于 Java8 开发的提供了近乎最佳命中率的高性能的缓存库。

在本地缓存方面,SpringFramework5.0(SpringBoot2.0)放弃了Google的GuavaCache,选择了「Caffeine」(Drop Guava caching - superseded by Caffeine [SPR-13797] #18370)。足以见证其在性能和可靠性上的优势.

其性能测试可以查看 https://github.com/ben-manes/caffeine/wiki/Benchmarks

Ehcache

Ehcache是纯Java开源缓存框架,配置简单、结构清晰、功能强大,是一个非常轻量级的缓存实现,我们常用的Hibernate里面就集成了相关缓存功能。

在早期开发的时候也用过这个,现在不知道是否还在使用

Memcached

一个高性能的、分布式的基于内存的key-value对象存储系统,用来存储小块的任意数据(字符串、对象)

通过访问其来较少数据库的读写压力

Redis

Redis 同样是一个高性能的基于内存中数据结构存储,用作数据库,缓存和消息代理。

它支持更多的数据结构,例如 strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes。

Redis具有内置的复制,Lua脚本,LRU逐出,事务和不同级别的磁盘持久性,并通过Redis Sentinel和Redis Cluster自动分区提供高可用性

Spring Cache

Spring Cache 并不是缓存的实现,而是一个缓存管理的抽象解决方案,这种方案消除了样板方法的使用,屏蔽了缓存的使用细节,而这是 Spring 最擅长干的.

Spring 的缓存技术还具备相当的灵活性,可以使用 SpEL 来定义缓存的 key 和各种 condition,提供了灵活的开箱即用的解决方案.

注意事项

在使用缓存的过程中,我们还要注意缓存不一致、缓存穿透、缓存击穿与缓存雪崩等问题,每种问题都是不小的问题

这篇写的并不长,每种都是简单介绍了一下,马上分几篇分别介绍一下各自的具体使用方法,敬请期待

参考

  1. spring cache
  2. https://github.com/google/guava/wiki/CachesExplained
  3. https://github.com/ben-manes/caffeine
  4. https://www.memcached.org/
  5. https://redis.io/

如果觉得还都凑合,记得 点赞、分享哦

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容