当然,在正常情况下是肯定无法做到这一点的,之少目前必须借助外界的力量,开源项目 Waffle Grid 就是我们需要借助的外部力量。
Waffle Grid 是国外的几位 DBA 在工作之余突发奇想出来的一个点子:既然 PC Server
的低廉成本如此的吸引我们,而其 Scale Up
的能力又很难有一个较大的突破,何不利用上现在非常流行的 Memcached
作为突破单台 PC Server
的内存上限呢?就在这个想法的推动下,几位小伙子启动了 Waffle Grid 这个开源项目,利用 MySQL
和 Memcached
双双开源的特性,结合 Memcached
通信协议简单的特点,将 Memcached
成功实现成为 MySQL
主机的外部“二级缓存”,目前仅支持用于 Innodb
的 Buffer Pool
。
Waffle Grid 的实现原理其实并不复杂,他所做的事情就是当 Innodb
在本地的 Buffer Pool
(我们姑且称其为 Local Buffer Pool
吧)的时候,在从磁盘数据文件读取数据之前,先通过 Memcached
的通信 API 接口尝试从 Memcached
中读取相应的缓存数据(我们称之为 Remote Buffer
吧),只有在 Remote Buffer
中也不存在需要的数据的时候, Innodb
才会访问磁盘文件来读取数据。而且,只有处于 Innodb Buffer pool
中的 LRU List
中的数据会被发送到 Remote Buffer Pool
中,而这些数据一旦被修改,就会 Innodb
就会将之移入 FLUSH List
,Waffle Grid
同时会将进入 FLUSH List
的数据从 Remote Buffer Pool
中清除掉。所以可以说,Remote Buffer Pool
中永远不会存在 Dirty Pages
,这也保证了当 Remote Buffer Pool
出现故障的时候不会产生数据丢失的问题。下图是使用 Waffle Grid 项目时候的架构简图:
如架构图上所示,我们首先在 MySQL
数据库端应用 Waffle Grid Patch
,通过他连与其他的 Memcached
服务器通信。为了保证网络通信的性能,MySQL
与 Memcached
之间尽可能用高带宽私有网络。
另外,这里的架构图中并没有再将数据库区分 Master
和 Slave
了,并不是说一定不能区分,只是一个示意图。在实际应用过程中,大部分时候只需要在 Slave
上面应用 Waffle Grid 即可,Master
本身并不需要如此大的内存。
看了 Waffle Grid 的实现原理,可能有些读者朋友会有些疑问了。这样做不是所有需要产生物理读的 Query
的性能就会受到直接影响了吗?所有读取 Remote Buffer
的操作都需要通过网络来获取,其性能是否足够高呢?对此,我同样使用作者对 Waffle
的实测数据来接触大家的疑虑:
通过 DBT2 所得到的这组测试对比数据,在性能我想并不需要太多的担忧了吧。至于 Waffle Grid 是否适合您的应用场景,那就只能依靠各位读者朋友自己进行评估了。
下面我们再来介绍一下 Memcached
和 MySQL
的另外一种整合方式,也就是通过 MySQL
所提供的 UDF 功能,自行编写相应的程序来实现 MySQL
与 Memcached
的数据通信更新操作。
这种方式和 Waffle Grid 不一样的是 Memcached
中的数据并不完全由 MySQL
来控制维护,而是由应用程序和 MySQL
一起来维护数据。每次应用程序从 Memcached
读取数据的时候,如果发现找不到自己需要的数据,则再转为从数据库中读取数据,然后将读取到的数据写入 Memcached
中。而 MySQL
则控制 Memcached
中数据的失效清理工作,每次数据库中有数据被更新或者被删除的时候,MySQL
则通过用户自行编写的 UDF 来调用 Memcached
的 API 来通知 Memcached
某些数据已经失效并删除该数据。
基于上面的实现原理,我们可以设计出如下这样的一个数据服务层架构:
如图中所示,此架构和上面将 Memcached
完全和 MySQL
读离开作为常规的 Cache 服务器来比较,最大的区别在于 Memcached
的数据变为由 MySQL
数据库来维护更新,而不是应用程序来更新。首先数据被应用程序写入 MySQL
数据库,这时候将会触发 MySQL
上面用户自行编写的相关 UDF,然后通过该 UDF 调用 Memcached
的相关通信接口,将数据写入 Memcached
。而当 MySQL
中的数据被更新或者删除的时候,MySQL
中的相关 UDF 同样会更新或者删除 Memcached
中的数据。当然,我们也可以让 MySQL
做更少一些的事情,仅仅只是遇到数据被更新或者删除的时候,通过 UDF 来删除 Memcached
中的数据,写入工作则像前面的架构一样由应用程序来作。
由于 Memcached
基于对象的数据存取,以及通过 Hash
进行数据检索的特性,所以所有存储在 Memcached
中的数据都需要我们设定一个用于标识该数据的 Key,所有数据的存取操作都通过该 Key 来进行。也就是说,如果您并不能像 MySQL
的 Query
语句一样通过某一个(或者多个)关键字条件来读取包含多条数据的结果集,仅适用于通过某个唯一键来获取单条数据的数据读取方式。
二、嵌入式数据库编程库 Berkeley DB
说实话,数据库编程库这个叫法实在有些别扭,但我也实在找不到其他合适的名词来称呼 Berkeley DB
了,那就姑且使用网上较为通用的叫法吧。
Memcached
所实现的是内存式 Cache,如果我们对性能的要求并没有如此之高,在预算方面也不是太充裕的话,我们还可以选择 Berkeley DB
这样的数据库型 Cache 软件。可能很多读者朋友又会产生疑惑了,我们使用的 MySQL
数据库,为什么还要再使用一个 Berkeley DB
这样的“数据库”呢?实际上 Berkeley DB
在之前也是 MySQL
的存储引擎之一,只不过后期不知道是何原因(获取与商业竞争有关吧),被 MySQL
从支持的存储引擎中移除了。之所以在使用数据库的同时还使用 Berkeley DB
这样的数据库型 Cache,是因为我们可以充分发挥出二者各自的优势,在使用传统通用型数据库的同时,同时可以利用 Berkeley DB
高效的键值对存储方式作为高效数据检索的性能补充,以得到更好的数据服务层扩展性和更高的整体性能。
Berkeley DB
自身架构可以分为五个功能模块,五个模块的在整个系统中相对比较独立,而且可以设置使用或者禁用某一个(或者几个)模块,所以可能称之为五个子系统会更为恰当一些。这五个子系统及基本介绍分别如下:
- 数据存取
数据存取子系统主要负责最主要也是最基本的数据存与取的工作。而且Berkeley DB
同时支持了以下四种数据的存储结果方式:Hash
,B-Tree
,Fixed Length
以及Dynamic Length
。实际上,这四种方式对应了四种数据文件存储的实际格式。数据存储子系统可以完全单独使用,也是必须开启的一个子系统。 - 事务管理
事务管理子系统主要是针对有事务要求的数据处理服务,提供完整的ACID
事务属性。在开启事务管理子系统的时候,出了需要开启最基本的数据存取子系统外,还至少需要开启锁管理子系统和日志系统来帮助实现事务的一致性和完整性。 - 锁管理
锁管理系统主要就是为了保证数据的一致性而提供的共享数据控制功能。支持行级别和页级别的锁定机制,同时为事务管理子系统提供服务。 - 共享内存
共享内存子系统我想大家看到名称就应该基本知道是做什么事情的了,就是用来管理维护共享Cache
和Buffer
的,为系统提升性能而提供数据缓存服务。 - 日志系统
日志系统主要服务于事务管理系统,为保证事务的一致性,Berkeley DB
也采用先写日志再写数据的策略,一般也都是与事务管理系统同时使用同时关闭。
基于 Berkeley DB
的特性,我们很难像使用 Memcached
那样将他和 MySQL
数据库结合的那么紧密。数据的维护与更新操作主要还是需要通过应用程序来完成。一般来说,在使用 MySQL
的同时还要使用 Berkeley DB
的主要原因就是为了提升系统的性能及扩展性。所以,大多数时候都主要是使用 Hash
和 B-Tree
这两种结构的数据存储格式,尤其是 Hash
格式,是使用最为广泛的,因为这种方式也是存取效率最高的。
在应用程序中,每次数据请求,都先通过预先设定的 Key
到 Berkeley DB
中取查找一次,如果存在数据,则返回取得的数据,如果位检索到数据,则再次到数据库中读取。然后将读取到的数据按照预先设定的 Key
,整条存入 Berkeley DB
中,再返回给客户端。而当发生数据修改的时候,应用程序在修改 MySQL
中的数据之后必须还要将 Berkeley DB
中的数据删除。当然,如果您愿意,也可以直接修改 Berkeley DB
中的数据,但是这样就可能引入更多的数据一致性风险并提高系统复杂度了。
从原理来看,使用 Berkeley DB
的方式和将 Memcached
作为纯 Cache
来使用差别不大嘛,为什么我们不用 Memcached
来做呢?其实主要有两个原因,一个是 Memcached
是使用纯内存来存放数据的,而 Berkeley DB
则可以使用物理磁盘,两者在成本方面还是有较大差别的。另外一个原因就是 Berkeley DB
所能支持的数据存储方式除了 Memcached
所使用的 Hash
存储格式之外,同时还可以使用其他存储格式,如 B-Tree
等。
由于和 Memcached
的基本使用原理区别不大,所以这里就不再画图示意了。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
![img](https://i-blog.csdnimg.cn/blog_migrate/99a8c02454a239b424a82fcb35f79110.jpeg)
2021年Java中高级面试必备知识点总结
在这个部分总结了2019年到目前为止Java常见面试问题,取其面试核心编写成这份文档笔记,从中分析面试官的心理,摸清面试官的“套路”,可以说搞定90%以上的Java中高级面试没一点难度。
本节总结的内容涵盖了:消息队列、Redis缓存、分库分表、读写分离、设计高并发系统、分布式系统、高可用系统、SpringCloud微服务架构等一系列互联网主流高级技术的知识点。
目录:
(上述只是一个整体目录大纲,每个点里面都有如下所示的详细内容,从面试问题——分析面试官心理——剖析面试题——完美解答的一个过程)
部分内容:
对于每一个做技术的来说,学习是不能停止的,小编把2019年到目前为止Java的核心知识提炼出来了,无论你现在是处于什么阶段,如你所见,这份文档的内容无论是对于你找面试工作还是提升技术广度深度都是完美的。
不想被后浪淘汰的话,赶紧搞起来吧,高清完整版一共是888页,需要的话可以点赞+关注
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!
+关注**
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!