高并发 高性能 高可用 MySQL 实战
第1章 课程介绍
本章对课程内容、知识点、授课过程进行引导性说明。
1. 问卷调查
你真的搞懂MySQL底层原理了吗?
你知道如何改善慢查询性能吗?
你知道如何架设高性能集群吗?
你知道未来数据库的发展趋势吗?
这些问题很重要! 因为….
工作中:MySQL高性能集群越来越流行
面试中:深入考察MySQL原理、性能调优
职业规划:需要根据技术发展方向选择职业路径
2. 精通MySQL 应该怎么学?从理论到实战
从数据表逻辑结构,到优化数据表的性能
从数据查询原理,到改善慢SQL性能
从单点到集群
从学习单点原理,到掌握集群原理
从高性能单点,到高性能集群
从单点快速部署,到集群快速部署
从现在到未来
从5.x版本,到8.0版本
从原生单体数据库,到原生分布式数据库
从学习技术原理,到理解技术趋势
以上三点就是本课程的主线
以技术原理作为坚实基础
以真实场景作为学习环境
以架构思维作为学习目标
3. 什么是“三高”
高并发:同时处理的事务数高
高性能:事务/SQL的执行速度高
高可用:系统可用时间高
为什么不直接讲“三高”“三高”只是目的,并不是手段,手段有 ...
MESI原理
由于 CPU 的运算速度远远的超过了内存的 IO 速度,因此在它和内存间又加了一层高速缓存,引入了缓存就必然带来一致性的问题。来看看这样的语句执行起来会是什么样的效果。 CPU b 先加载了 n=1,然后cpuA也加载了n,还进行了n+1的操作,这时候 CPU b 再去获取 n 的值。由于高速缓存中已经有值了,所以他拿到的还是n=1,产生了不一致的情况。 CPU 厂商为了解决这样的情况,引入了缓存一致性的协议。常见的比如说MESI,它有四个状态对应着修改、独占、共享、失效,而这四种状态又能量转换形成 16 种情况,这其实就是一个状态机。这个状态机看得我都头大,其实我们没有必要去了解得很透彻,继续用刚刚的例子走一遍流程,看看它是如何保证一致性的。
CPU b 先获取 n 的值,这时候它是独占状态,然后 CPU a 在获取 n 的时候,通过总线地址冲突检测到 b 有这个值,于是向 b 请求这个值,这时候 n 变成了共享状态。当 CPU a 要修改 n 的时候,会通过总线发出失效命令,让 b 的高速缓存对应的 n 的状态变为失效。收到 ACK 后让本地的 n 变为独占状态 ...
面试杂谈
MYSQL alter操作alter应该不会锁表吧 就会加一个MDL锁 innoDB支持在线DDL alter的时候不会阻塞对表的读写,然后百度 alert千万数据表的时候需要使用percona的 pt-online-schema-change ,他会建立一个与原来表结构相同的新表,然后把数据全部复制过去,最后替换表来完成大数据量表新增一个字段。
volatile这个是为了各个核心数据一致性的,有修改缓冲区和失效队列,但是修改缓冲区的内容什么时候刷新到主内存,核心什么时候操作失效队列,这个是核心自己来控制的在并发场景下,核心自己控制就会出问题所以需要屏障来告诉核心什么时候操作。java提供了关键字对底层原理封装,由开发人员来决定怎么做,volatile就是屏障,来告诉核心这个时候该刷新主内存,操作失效队列了
7.常见的MESI协议就是基于总线嘎探实现的。
8.MESI解决了缓存一致性问题,但是还是不能将CPU性能压榨到极致。
9.为了进一步压榨CPU,所以引入了 store buffer 和invalidate queue。
10.store buffer和invalidate q ...
一些面试笔记
解释下Java线程池的各个参数的含义?在JDK当中,创建线程值的API为ThreadPoolExector类,这个类的构成方法当中就包含了创建线程值的几个核心参数。第一个corePoolSize用于设置线程池里面的核心线程数量maxPoolSize用于设置线程池里面允许的最大线程数量keepAliveTime用于设置当线程数量大于corePoolSize多出来空闲的线程将会在keepAliveTime之后就会被释放掉。unit用于设置keepAliveTime时间单位,比如秒钟、分钟等。workQueen用于设置等待队列,ThreadFactory用于设置每当创建新的线程放入线程值的时候,就会是就是通过这个线程工厂来创建的。handler用于设置就是说当线程等待队列都满了之后采取的策略,比如抛出异常等策略。那我们假设一组参数值来说明一下这些参数的含义。假设我们设置corePoolSize为1,maxPoolSize为3,keepAliveTime为60秒,workQueen为ArrayBrokingQueen有界阻塞队列大小为4,handler了默认的策略抛出一个所的threadRej ...
使用kubeadm快速部署一个K8s集群
kubeadm是官方社区推出的一个用于快速部署kubernetes集群的工具。
这个工具能通过两条指令完成一个kubernetes集群的部署:
12345# 创建一个 Master 节点$ kubeadm init# 将一个 Node 节点加入到当前集群中$ kubeadm join <Master节点的IP和端口 >
1. 安装要求在开始之前,部署Kubernetes集群机器需要满足以下几个条件:
一台或多台机器,操作系统 CentOS7.x-86_x64
硬件配置:2GB或更多RAM,2个CPU或更多CPU,硬盘30GB或更多
可以访问外网,需要拉取镜像,如果服务器不能上网,需要提前下载镜像并导入节点
禁止swap分区
2. 准备环境
角色
IP
master
192.168.1.11
node1
192.168.1.12
node2
192.168.1.13
使用kubeadm方式搭建K8s集群主要分为以下几步
准备三台虚拟机,同时安装操作系统CentOS 7.x
对三个安装之后的操作系统进行初始化操作
在三个节点安装 docker ku ...
单机Kubernetes安装
安装 kubectl
下载对应版本的kubectl
下载一个可执行文件,加入到PATH环境变量即可
需要指定版本直接换版本即可(我安装是1.17,直接脚本中替换为v1.17.0即可)
12345678# Linuxcurl -LO https://dl.k8s.io/release/v1.22.0/bin/linux/amd64/kubectl# Maccurl -LO "https://dl.k8s.io/release/v1.22.0/bin/darwin/arm64/kubectl"# Windowscurl -LO "https://dl.k8s.io/release/v1.22.0/bin/windows/amd64/kubectl.exe"
配置PATH环境变量
12345678910# 给下载的kubectl 赋予权限chmod +x kubectl# kubectl 放到当前用户家目录下.local/bin/下(可以直接放到PATH环境变量下即可譬如/usr/local/bin下)mkdir -p ~/.local/b ...
Spring是如何使用三级缓存来解决循环依赖问题?
1.什么是循环依赖?假设我们有两个类 A 和 B,类A和类B的实例互为成员变量即为循环依赖。
当然也有可能是一个类,或三个类间进行循环依赖。
2.什么是Spring的循环依赖?我们这里还是拿上面类 A 和 B 来举例:
补充知识:Bean的声明周期如下:
当 Spring 框架启动后,开始根据注解将类 A 实例化并注入到容器当中,在实例化 A 之后就会尝试获取类 B 的实例来进行依赖注入。
由于类 B 并没有进行实例化,那么 Spring 框架就会去实例化类 B,同样的也会需要将类 A 的依赖注入到类 B 的实例中:
最终,无论先实例化哪个类,都会形成死循环。
简化后如下所示:
3.三级缓存解决循环依赖Spring 框架解决循环依赖是通过三级缓存,对应的三级缓存如下所示:
12345678910// 单实例对象注册器public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry { private static fina ...
MySQL两阶段提交.md
两阶段提交的过程是怎样的?
从图中可看出,事务的提交过程有两个阶段,就是将redoLog的写入拆成了两个步骤:prepare和commit,中
间再穿插写入binlog,具体如下:
1:prepare阶段:将XID(内部XA事务的ID)写入到redo log buffer,同时将redo log对应的事务状态设置为prepare,然后将redo log持久化到磁盘(innodb_flush_log_at_trx_commit=1的作用);
2:commit阶段:把XID写入到binlog cache,然后将binlog持久化到磁盘(sync_binlog=1的作用),接着调用引擎的提交事务接口,将redo log状态设置为commit,此时该状态并不需要持久化到磁盘,只需要write到文件系统的page cache中就够了,因为只要binlog写磁盘成功,就算redo log的状态还是prepare也没有关系,一样会被认为事务已经执行成功;
为什么需要两阶段提交?如果只写一次的话,那到底先写bin-log还是redo-log呢?
先写bin-log,再写redo-l ...
Elasticsearch数据写入
es的架构简介首先,从架构的角度来看,Elasticsearch是一个分布式的搜索和分析引擎,它能够存储、搜索和分析大量数据。为了实现这些功能,Elasticsearch采用了分片和副本的机制,使得数据可以分布在多个节点上,并且具有容错性和可扩展性。简要介绍Elasticsearch的架构:
1. 分布式架构节点与集群:Elasticsearch由多个节点(Node)组成,这些节点可以组成一个集群(Cluster)。每个节点都可以处理读写请求,并且数据在集群中的节点之间进行分布和复制,以实现高可用性和扩展性。
分片与副本:为了支持大规模数据,Elasticsearch将索引划分为多个分片(Shard),每个分片可以独立存储和处理数据。此外,每个分片可以有多个副本(Replica),用于提供数据冗余、故障恢复和读取负载均衡。
2. 索引与搜索倒排索引:Elasticsearch使用Lucene作为其底层的搜索库。Lucene构建倒排索引(Inverted Index)来加速搜索过程。倒排索引将文档中的单词映射到包含这些单词的文档列表,从而实现快速查找和检索。
查询执行:当客户端发送搜索 ...
三色标记法
JVM(Java虚拟机)中的三色标记法是一种用于垃圾收集(Garbage Collection, GC)的算法,尤其在CMS(Concurrent Mark Sweep)和G1(Garbage First)等并发收集器中广泛使用。该算法通过将对象标记为三种不同的颜色来追踪和识别垃圾对象,从而在不发生或尽可能短地发生STW(Stop The World,即全线程停顿)的情况下进行垃圾收集。以下是三色标记法的详细介绍:
三色标记法的颜色定义
白色:表示对象尚未被垃圾收集器访问过。在可达性分析刚开始的阶段,所有的对象都是白色的。如果在分析结束的阶段,对象仍然是白色的,则表示该对象不可达,即被认为是垃圾。
灰色:表示对象已经被垃圾收集器访问过,但这个对象上至少存在一个引用还没有被扫描过。在扫描过程中,垃圾收集器会从灰色对象出发,继续扫描其引用的其他对象。
黑色:表示对象已经被垃圾收集器访问过,并且这个对象的所有引用都已经被扫描过。黑色对象是安全存活的,不会被作为垃圾回收。
三色标记法的流程
初始状态:所有对象都是白色的。
根节点标记:将GC Roots(如线程栈、静态变量等)直接可达的对象标 ...






