12 道 Java 高级面试题:瞧一瞧
父类构造为:
构造参数含义:
corePoolSize : 核心池大小
maximumPoolSize : 最大线程数
keepAliveTime: 线程没有任务执行时, 最多能够存活多久
timeUnit: 时间单位
workQueue: 阻塞任务队列
threadFactory: 线程工厂, 用来创建线程
2.MyCat 线程架构
在 MyCat 中主要有两大线程池: timerExecutor 和 businessExecutor。
timerExecutor线程池主要完成系统时间定时更新、处理器定时检查、数据节点定时连接空闲超时检查、数据节点定时心跳检测等任务。businessExecutor是 MyCat 最重要的线程资源池, 该资源池的线程使用的范围非常广, 涵盖以下方面:
A.后端用原生协议连接数据
B.JDBC 执行 SQL 语句
C.SQL 拦截
D.数据合并服务
E.批量 SQL 作业
F.查询结果的异步分发
G.基于 guava 实现异步回调
参考资料:
《开源数据库中间件MyCat实战笔记》快速入手通道:发送简信“MyCat资料”免费获取
二、MyCat 内存管理及缓存框架与实现
这里所提到的内存管理指的是 MyCat 缓冲区管理, 众所周知设置缓冲区的唯一目的是提高系统的性能,缓冲区通常是部分常用的数据存放在缓冲池中以便系统直接访问, 避免使用磁盘 IO 访问磁盘数据, 从而提高性能。
1.内存管理
A.缓冲池组成
缓冲池的最小单位为 chunk, 默认的 chunk 大小为 4096 字 (DEFAULT_BUFFER_CHUNK_SIZE),BufferPool的总大小为4096 x processors x 1000(其中processors为处理器数量)。对 I/O 进程而言, 他们共享一个缓冲池。缓冲池有两种类型: 本地缓存线程(以 $_开头的线程)缓冲区和其他缓冲区, 分配buffer时, 优先获取ThreadLocalPool中的buffer, 没有命中时会获取BufferPool中的buffer。
B.分配 MyCat 缓冲池
分配缓冲池时, 可以指定大小, 也可以用默认值。
A.allocate(): 先检测是否为本地线程, 当执行线程为本地缓存线程时, localBufferPool 取出一个可用的 buffer。如果不是, 则从 ConcurrentLinkedQueue 队列中取出一个 buffer 进行分配, 如果队列没有可用的 buffer, 则创建一个直接缓冲区。
B.allocate(size): 如果用户指定的 size 不大于chunkSize, 则调用allocate()进行分配;反之则调用createTempBuffer(size)创建临时非直接缓冲区。
C.MyCat 缓冲池的回收
回收时先判断 buffer 是否有效, 有如下情况时缓冲池不回收。
A.不是直接缓冲区
B.buffer 是空的
C.buffer 的容量大于 chunkSize
2.MyCat 缓存架构
A.缓存框架选择
MyCat 支持 ehcache、mapdb、leveldb 缓存, 可通过配置文件cacheserver.properties来进行配置;
B.缓存内容
MyCat 有路由缓存、表主键到 datanode 缓存、ER 关系缓存。
A.路由缓存: 即SQLRouteCache, 根据 SQL 语句查找路由信息的缓存, 该缓存只是针对 select 语句, 如果执行了之前已经执行过的某个 SQL 语句(缓存命中), 那么路由信息就不需要重复计算了, 直接从缓存中获取。
B.表主键到 datanode 缓存: 当分片字段与主键字段不一致时, 直接通过主键值查询时无法定位具体分片的(只能全分片下发), 所以设置该缓存之后, 就可以利用主键值查找到分片名, 缓存的 key 是 ID 值, value 是节点名。
C.ER 关系缓存: 在 ER 分片时使用, 而且在 insert 查询中才会使用缓存, 当字表插入数据时, 根据父子关联字段确定子表分片, 下次可以直接从缓存中获取所在的分片。
查看缓存指令: show @@cache;
三、MyCat 连接池架构与实现
这里我们所讨论的连接池是 MyCat 的后端连接池, 也就是 MyCat 后端与各个数据库节点之间的连接架构。
A.连接池创建
MyCat 按照每个 dataHost 创建一个连接池, 根据schema.xml文件的配置取得最小的连接数minCon,并初始化minCon个连接。在初始化连接时, 还需要判定用户选择的是JDBC还是原生的MySQL协议,以便于创建对应的连接。
B.连接池分配
分配连接就是从连接池队列中取出一个连接, 在取出一个连接时, MyCat 需要根据 负载均衡(balance 属性) 的类型选择不同的数据源, 因为连接和数据源绑在一起,所以需要知道 MyCat 读写的是那些数据源, 才能分配响应的连接。
C.架构
四、MyCat 主从切换架构与实现
1.MyCat 主从切换概述
MyCat 实现 MySQL 读写分离的目的在于降低单节点数据库的访问压力, 原理就是让主数据库执行增删改操作, 从数据库执行查询操作, 利用 MySQL 数据库的复制机制将Master的数据同步到slave上。
当 master 宕机后,slave 承载的业务如何切换到master继续提供服务,以及 slave 宕机后如何将master切换到slave上。手动切换数据源很简单, 但不是运维工作的首选,本文重点就是讲解如何实现自动切换。
MyCat 的读写分离依赖于 MySQL 的主从同步, 也就是说 MyCat 没有实现数据的主从同步功能, 但是实现了自动切换功能。
A.自动切换
自动切换是 MyCat 主从复制的默认配置 , 当主机或从机宕机后, MyCat 自动切换到可用的服务器上。假设写服务器为 M, 读服务器为 S, 则:
正常时, 写 M 读 S;
当 M 宕机后, 读写 S ; 恢复 M 后, 写 S, 读 M ;
当 S 宕机后, 读写 M ; 恢复 S 后, 写 M, 读 S ;
B.基于 MySQL 主从同步状态的切换
这种切换方式与自动切换不同, MyCat 检测到主从数据同步延迟时, 会自动切换到拥有最新数据的 MySQL 服务器上, 防止读到很久以前的数据。
原理就是通过检查 MySQL 的 主从同步状态(show slave status) 中的Seconds_Behind_Master、Slave_IO_Running、Slave_SQL_Running三个字段,来确定当前主从同步的状态以及主从之间的数据延迟。 Seconds_Behind_Master为 0 表示没有延迟,数值越大,则说明延迟越高。
2.MyCat 主从切换实现
基于延迟的切换, 则判断结果集中的Slave_IO_Running、Slave_SQL_Running两个个字段是否都为 yes,以及Seconds_Behind_Master 是否小于配置文件中配置的 slaveThreshold的值,如果有其中任何一个条件不满足, 则切换。
主要流程如下:
五、MyCat 核心技术
1.MyCat 分布式事务实现
MyCat 在 1.6 版本以后已经支持 XA 分布式事务类型了。具体的使用流程如下:
在应用层需要设置事务不能自动提交
更多:Java 进阶核心知识集
包含:JVM,JAVA 集合,网络,JAVA 多线程并发,JAVA 基础,Spring 原理,微服务,Zookeeper,Kafka,RabbitMQ,Hbase,MongoDB,Cassandra,设计模式,负载均衡,数据库,一致性哈希,JAVA 算法,数据结构,加密算法,分布式缓存等等
点击免费领取我的学习笔记:学习视频+大厂面试真题+微服务+MySQL+Java+Redis+算法+网络+Linux+Spring全家桶+JVM+学习笔记图
高效学习视频











评论