加入收藏

当前简讯:缓存世界里,那些强大又隐秘的扫地僧

2023-06-26 04:32:01 来源:博客园

扫地僧,是金庸武侠小说《天龙八部》中的人物。


【资料图】

他的来历没有太多描述,负责打扫藏经阁,神秘而且武功深不可测,并具有大智慧,有极高技艺却深藏不露,隐匿在少林寺默默无闻。

这篇文章,笔者想聊聊缓存,只不过并不是大家耳熟能详的 Redis ,而是那些隐藏在中间件或者框架中强大却又隐秘的缓存,笔者愿称他们为缓存世界的扫地僧

1 HashMap/ConcurrentHashMap 配置缓存

HashMap 是一种基于哈希表的集合类,它提供了快速的插入、查找和删除操作。可以将键值对作为缓存项的存储方式,将键作为缓存项的唯一标识符,值作为缓存项的内容。

HashMap 是很多程序员接触的第一种缓存 , 因为现实业务场景里,我们可能需要给缓存添加缓存统计过期失效淘汰策略等功能,HashMap 的功能就显得孱弱 ,所以 HashMap 在业务系统中使用得并不算多。

HashMap 在中间件中却是香饽饽,我们消息中间件 RocketMQ 为例。

上图是 RocketMQ 的集群模式 ,Broker 分为 Master 与 Slave,一个 Master 可以对应多个 Slave,但是一个 Slave 只能对应一个 Master。

每个 Broker 与 Name Server 集群中的所有节点建立长连接,定时每隔 30 秒注册 主题的路由信息到所有 Name Server。

消息发送者、消息消费者,在同一时间只会连接 Name Server 集群中的一台服务器,并且会每隔 30s 会定时更新 Topic 的路由信息。

我们可以理解 Name Server 集群的作用就是注册中心,注册中心会保存路由信息(主题的读写队列数、操作权限等),路由信息就是保存在 HashMap中 。

路由信息通过几个 HashMap 来保存,当 Broker 向 Nameserver 发送心跳包(路由信息),Nameserver 需要对 HashMap 进行数据更新,但我们都知道 HashMap 并不是线程安全的,高并发场景下,容易出现 CPU 100% 问题,所以更新 HashMap 时需要加锁,RocketMQ 使用了 JDK 的读写锁 ReentrantReadWriteLock 。

下面我们看下路由信息如何更新和读取:

1、写操作:更新路由信息,操作写锁

2、读操作:查询主题信息,操作读锁

同时,我们需要注意 Name Server 维护路由信息还需要定时任务的支撑。

每个 Broker 定时每隔 30 秒注册 主题的路由信息到所有 Name ServerName Server 定时任务每隔10 秒清除已宕机的 Broker

我们做一个小小的总结,Name Server 维护路由的模式是: HashMap + 读写锁 + 定时任务更新

HashMap 作为存储容器读写锁控制锁的颗粒度定时任务定时更新缓存

写到这里,我们不禁想到 ConcurrentHashMap 。

ConcurrentHashMap 可以保证线程安全,JDK1.7 之前使用分段锁机制实现,JDK1.8 则使用数组+链表+红黑树数据结构和CAS原子操作实现。

Broker 使用不同的 ConcurrentHashMap 分别用来存储消费组、消费进度、消息过滤信息等。

那么名字服务为什么不使用 ConcurrentHashMap 作为存储容器呢 ?

最核心的原因在于:路由信息由多个 HashMap 组成,通过每次写操作可能要操作多个对象 ,为了保证其一致性,所以才需要加读写锁。

2 LinkedHashMap 最近最少使用缓存

LinkedHashMap 是 HashMap 的子类,但是内部还有一个双向链表维护键值对的顺序,每个键值对既位于哈希表中,也位于双向链表中。

LinkedHashMap 支持两种顺序插入顺序 、 访问顺序

插入顺序:先添加的在前面,后添加的在后面,修改操作并不影响顺序访问顺序:问指的是 get/put 操作,对一个键执行 get/put 操作后,其对应的键值对会移动到链表末尾,所以最末尾的是最近访问的,最开始的是最久没有被访问的,这就是访问顺序。

LinkedHashMap 经典的用法是作为 LruCache (最近最少使用缓存) ,而 MyBatis 的二级缓存的淘汰机制就是使用的 LinkedHashMap 。

MyBatis 的二级缓存是使用责任链+ 装饰器的设计模式实现的,虽然 Mybatis 的二级缓存功能在生产环境并不推荐使用,但它的设计模式还是值得学习。

上图中,装饰器包目录下 Cache 接口有不同的实现类,比如过期淘汰日志记录等。

LruCache 使用了装饰器模式 ,使用 LinkedHashMap 默认保存 1024 个缓存 key ,当 key 最久未被访问,并且 keyMap 的大小超过 1024 时 ,记录最老的 key ,当下次添加缓存对象时,删除最老的 key。

使用 LinkedHashMap 重点需要做到使用访问顺序模式重写 removeEldestEntry 方法。 因为 LinkedHashMap 并不是线程安全的,Mybatis 二级缓存责任链中 SynchronizedCache 对象可以实现线程安全的对缓存读写。

3 TreeMap 排序对象缓存

TreeMap 是一种基于红黑树的有序 Map,它可以按照键的顺序进行遍历。

一致性哈希(Consistent Hashing)算法被广泛应用于缓存系统、分布式数据库、负载均衡器等分布式系统中,以实现高性能和高可用性。它解决了传统哈希算法在动态环境下扩展性和负载均衡性能的问题。

一致性哈希的主要优点是在节点增减时,只有少量的数据需要重新映射,因为只有那些直接或间接与新增或删除节点相邻的数据项需要迁移。这大大减少了系统的迁移开销和影响,使得系统更具扩展性和可伸缩性。

TreeMap 在一致性哈希中可以用作节点/虚拟节点的存储结构,用来维护节点在哈希环上的位置和键的有序性。

1、我们定义一个 TreeMap 存储节点/虚拟节点 。

2、初始化节点

构造函数包含三个部分:物理节点集合、每个物理节点对应的虚拟节点个数、哈希函数 。

我们重点看下添加节点逻辑:

3、按照 key 查询节点

添加完节点之后,节点分布类似下图:

当需要定位某个 key 属于哪个节点时,先通过哈希函数计算 key 的哈希值,并在环上顺时针方向找到第一个大于等于该哈希值的节点位置。该节点即为数据的归属节点 。

我们添加一个新的节点 node5 , 从下图中,我们可以看到,影响的范围(深黄色)并不大 ,这也就是一致性哈希算法的优势。

4 ByteBuffer 网络编程缓冲池

ByteBuffer 是字节缓冲区,主要用于用户读取和缓存字节数据,多用于网络编程、文件 IO 处理等。

笔者第一次接触 ByteBuffer 是在分库分表中间件 Cobar 中 。在网络编程里,经常需要分配内存,在高并发场景下,性能压力比较大。

Cobar 抽象了一个 NIOProcessor 类用来处理网络请求,每个处理器初始化的时候都会创建一个缓冲池 BufferPool 。 BufferPool 用于池化 ByteBuffer ,这和我们平常使用的数据库连接池的思路是一致的。

下图展示了缓冲池 BufferPool 的源码:

缓冲池 BufferPool 的核心功能是分配缓存回收缓存,通过将缓存池化,可以大大提升系统的性能。

如今 ,Netty 内置了更为强大的内存池化工具 ByteBuf ,我们会在后面的文章里详聊。

5 写到最后

这篇文章,笔者总结了四种非常强大且隐秘的缓存。

1、HashMap/ConcurrentHashMap 经常用于配置缓存,对于 HashMap 来讲,HashMap + 读写锁 + 定时任务更新是常用的模式。而 ConcurrentHashMap 广泛存在于各种中间件,线程安全且灵活易用。

2、LinkedHashMap 经常被用于创建最近最少使用缓存 LruCache 。推荐学习 Mybatis 二级缓存的设计,它使用责任链+ 装饰器的设计模式,内置 LruCache 的实现就是使用 LinkedHashMap 。

3、TreeMap 是一种基于红黑树的有序 Map 。TreeMap 在一致性哈希中可以用作节点/虚拟节点的存储结构,用来维护节点在哈希环上的位置和键的有序性。

4、ByteBuffer 是字节缓冲区,主要用于用户读取和缓存字节数据,多用于网络编程、文件 IO 处理等。分库分表中间件 Cobar 在网络请求处理中,创建了缓冲池 BufferPool 用于池化 ByteBuffer ,从而大大提升系统的性能。

如果我的文章对你有所帮助,还请帮忙点赞、在看、转发一下,你的支持会激励我输出更高质量的文章,非常感谢!

关键词:

相关新闻

资讯

毛利率堪比茅台,研发人员仅8人,敷尔佳IPO后能走多远?
毛利率堪比茅台,研发人员仅8人,敷尔佳IPO后能走多远?

而站在高毛利金字塔尖的茅台,2022年毛利率为92 6%,......更多>

钻石价格,突发“跳水”!未来还会更便宜?_世界短讯
钻石价格,突发“跳水”!未来还会更便宜?_世界短讯

报道称,2020年时,人造钻石的市场销售份额仅为2 4%......更多>

瓜果丰收 乐了萌娃
瓜果丰收 乐了萌娃

null近日,浙江省丽水市缙云县新区实验幼儿园的小朋友......更多>

环球即时看!端午节假期出游人次破亿,文旅产品服务丰富
环球即时看!端午节假期出游人次破亿,文旅产品服务丰富

新华社北京6月24日电(记者徐壮)文化和旅游部24日公......更多>

观速讯丨信达地产:聘任宗卫国为公司副总经理
观速讯丨信达地产:聘任宗卫国为公司副总经理

6月25日信达地产公告称根据信达地产股份有限公司以下......更多>

2023上海公积金封存后怎么解除的
2023上海公积金封存后怎么解除的

上海公积金集中封存由原单位在30日内将该职工结余的住......更多>

工商银行兔年金条100g价格今天多少一克(2023年06月25日)
工商银行兔年金条100g价格今天多少一克(2023年06月25日)

金投网提供工商银行兔年金条100g价格今天多少一克(20......更多>

世界快播:I华恒股份回复问询超时被终止审核,股权代持与纠纷屡被关注
世界快播:I华恒股份回复问询超时被终止审核,股权代持与纠纷屡被关注

来源:第一财经两家公司在问询后撤材料。6月19日~6月2......更多>

每日快报!月均增长达“百亿级” 六问快递业如何实现提速发展
每日快报!月均增长达“百亿级” 六问快递业如何实现提速发展

荔枝、樱桃、哈密瓜,生鲜、冷链、次日达。一辆辆快递......更多>

秦穆公尝出而亡其骏马自往求之翻译 秦穆公尝出而亡其骏马_天天新资讯
秦穆公尝出而亡其骏马自往求之翻译 秦穆公尝出而亡其骏马_天天新资讯

1、1.见人已杀其马/方共食其肉。2、2.骏马被人宰杀......更多>

关注

数码宝贝:神圣天使兽是否真有实力,能打赢小丑皇纯属侥幸?-环球速看料
数码宝贝:神圣天使兽是否真有实力,能打赢小丑皇纯属侥幸?-环球速看料
神圣天使兽是巴达兽的超进化形态,初次登场于和小丑... 更多>
数码宝贝:神圣天使兽是否真有实力,能打赢小丑皇纯属侥幸?-环球速看料
神圣天使兽是巴达兽的超进化形态,初次登场于和小丑... 更多>
男子开定速巡航和刹车失灵:刹车踩不下去 方向盘很硬
男子开定速巡航和刹车失灵:刹车踩不下去方向盘很硬 更多>
专家“下沉”,谁受益?——吕梁市人民医院组团引进“北京名医”的启示|世界球精选
4月21日,吕梁市人民医院整体搬迁至吕梁市医疗卫生园... 更多>
2023东莞中考东城哪些路段有交通管制? 每日动态
东莞市2023年初中学业水平考试定于6月26日至28日举行... 更多>
“上头电子烟油”含大麻,两人朋友圈售卖均被判刑
南都讯记者赵青近年来,一些违法犯罪分子利用电子烟这... 更多>
全球连线|在关于中西方制度比较的辩论中,这位法国企业家力挺中国 天天观焦点
新华社北京6月24日电(记者刁泽)4月初,一场关于中西... 更多>
2023年高考志愿填报十问十答来了-世界视讯
2023年高考志愿填报十问十答来了 更多>
鹏博士:入选“北京算力互联互通平台二期成果”并成为平台接入服务商_焦点快报
【鹏博士:入选“北京算力互联互通平台二期成果”并成... 更多>
环球动态:1-4惨败!迈阿密国际18轮15分+进17球,梅西来也带不动,不会降级
本轮美职联,迈阿密国际做客对阵费城联合,结果他们1-... 更多>
当前动态:用户指南_关于用户指南介绍
用户指南,关于用户指南介绍这个很多人还不知道,我们... 更多>
释放健康消费需求,SKG拿下618 “全场连胜”|全球观察
从618“开门红”到“整场连胜”,再次彰显了SKG在按摩... 更多>
侠客风云传酸梅在哪?酸梅的用法和功效是什么?_世界今头条
侠客风云传酸梅在哪?方法一、这种方法在杭州进行,首... 更多>