集合是 Java 面试和日常开发出场率最高的知识点,没有之一。本文不聊并发容器(ConcurrentHashMap、CopyOnWriteArrayList 的细节已在《Java 并发编程核心》一文中拆解过),而是聚焦单线程场景下的集合骨架:ArrayList 为什么扩容是 1.5 倍?HashMap 为什么容量必须是 2 的幂?链表为什么树化阈值是 8?LinkedHashMap 如何三行代码实现 LRU?把这些问题一次讲透。
一、集合框架全景图Java 集合框架以两个顶层接口为根:Collection(单元素)和 Map(键值对)。
123456789Iterable └── Collection ├── List(有序、可重复):ArrayList / LinkedList / Vector ├── Set(不可重复):HashSet / LinkedHashSet / TreeSet └── Queue(队列):ArrayDeque / PriorityQueue / LinkedListMap(独立体系) ├── HashMap → Linke ...
Vue 2 用 Object.defineProperty 做响应式,遇到”新增属性不更新””数组索引改了没反应”只能靠 $set 打补丁。Vue 3 把底层换成了 Proxy,从根上解决了这些坑。本文把响应式的”任督二脉”——依赖收集与派发更新——彻底拆开,再看 Composition API 怎么把逻辑组织得更干净。
一、为什么 Vue 2 的响应式不够用Vue 2 在初始化时递归遍历 data,用 Object.defineProperty 给每个属性加 getter/setter。这带来三个绕不开的硬伤:
痛点
现象
Vue 2 的妥协方案
新增属性无响应
this.obj.newKey = 1 视图不更新
必须用 this.$set(obj, 'newKey', 1)
删除属性无响应
delete this.obj.key 视图不更新
必须用 this.$delete(obj, 'key')
数组索引/length 监听不到
arr[0] = x / arr.length = 0 不触发
重写数组 7 个方法(push ...
很多系统一开始用”直接调接口”把服务串起来,随着流量和依赖变多,耦合、峰值、故障扩散会接踵而至。Kafka 不是单纯的”消息中间件”,它更像一套分布式的提交日志系统。本文从原理到实战,把 Kafka 最容易被问、最容易踩坑的部分一次讲透。
一、为什么需要 Kafka:消息队列解决了什么在一个典型后端系统里,订单服务可能要同时通知库存、积分、风控、物流。如果全部用同步 RPC 调用,任何一个下游抖动都会拖垮下单链路。消息队列的价值可以用一张表概括:
痛点
同步直连
引入消息队列(Kafka)
耦合
A 直接依赖 B/C/D,改一个要动一片
只依赖 Topic,下游可随时增减
峰值
流量洪峰直接打垮数据库
broker 缓冲,消费者按能力消费(削峰填谷)
失败扩散
库存超时导致下单失败
消息持久化,下游恢复后继续消费
能力扩展
新增消费者要改调用方
直接加 Consumer 即可扩容
Kafka 的”本领”不止异步解耦:它还天然支持流处理(Kafka Streams / Flink 接入)、事件溯源、日志聚合和多副本容灾。当你需要的不是”发个通知”,而 ...
线程池解决了”怎么管理线程”的问题,但线程池本身并不保证线程安全——它只是把任务交给线程执行。真正保证多线程正确协作的,是 volatile、synchronized、CAS 和 AQS 这套并发原语。本文从 JMM 内存模型讲起,把 Java 并发的”内功心法”彻底拆开。
一、JMM 内存模型:并发问题的根源Java 多线程程序中出现的各种诡异 Bug——值没变、结果不对、指令乱序——归根结底都源于 JMM(Java Memory Model)。JMM 不是真实存在的硬件结构,而是一组规范,定义了线程如何通过主内存交互。
1.1 三大特性:可见性、原子性、有序性
特性
含义
违反时的现象
保证手段
可见性
一个线程修改了共享变量,其他线程能立即看到最新值
线程 A 改了 flag=true,线程 B 还在读到 false
volatile / synchronized / final
原子性
一个操作不可分割,要么全部完成,要么全不做
i++ 看起来是一行,实际是 读-改-写 三步
synchronized / Lock / Atomic
有序性
程序按照代码 ...
索引、事务、复制、分库、备份解决的是“能不能跑、跑得快不快、丢不丢数据”的问题;而安全解决的是“谁能进来、进来能干什么、干了什么能不能被追溯”的问题。MySQL 的安全事故,80% 不是被黑客攻破,而是账号权限过大、密码太弱、连接不加密、操作没审计导致的。本文聚焦权限、加密与审计这三根支柱。
一、安全设计的三个原则在动手改权限之前,先统一认识:
最小权限原则:一个账号只拥有完成工作所需的最小权限集合,能只读就不给写,能只访问一个库就不给所有库。
纵深防御原则:安全不能只靠某一层,权限 + 密码 + 网络 + 应用层 + 审计要同时生效。
可追溯原则:关键操作必须留痕,知道谁在什么时间做了什么,出了问题能回溯。
这三条会贯穿后面的所有配置。
二、MySQL 账号与权限模型2.1 user@host 的含义MySQL 的账号不是单纯的用户名,而是 用户名 + 允许登录的主机 的组合。
1234-- 三个完全不同的账号'app_user'@'10.0.0.%''app_user'@'app-server-01 ...
索引优化、事务锁、主从复制和分库分表能帮你“跑得快、扛得住”,但数据一旦误删、磁盘损坏或勒索软件加密,backup 才是最后一道防线。本文聚焦 MySQL 备份与恢复:从 mysqldump 到 XtraBackup,再到 binlog 定点恢复,把“能回滚”这件事讲透。
一、备份是最后一道防线很多团队把备份当成“有就行”,直到出事才发现:
备份文件损坏,无法解压。
只备份了 schema,没备份数据。
恢复演练从没做过,真正恢复时耗时半天。
binlog 没开,误删后只能回档到昨晚的全量。
所以备份的核心目标不只是“存一份数据”,而是在可接受的时间内,恢复到可接受的状态。
二、备份分类与策略2.1 逻辑备份 vs 物理备份
维度
逻辑备份(mysqldump)
物理备份(XtraBackup)
形式
SQL 文本 / CSV
数据文件副本
速度
慢(逐行导出)
快(拷贝页 + redo)
体积
大,可压缩
接近原库,可压缩
恢复
逐条执行 SQL
直接替换数据文件
适用
小库、跨版本、部分表
大库、生产全量、热备
一致性
--single-tr ...
主从复制和读写分离能扛住读流量,却扛不住写流量无限增长。当单库写性能、磁盘容量或连接数触及天花板时,分库分表就成了必经之路。本文从拆分策略讲到 ShardingSphere 落地,帮你把“拆”这件事拆明白。
一、单库撑不住时,先别急着分分库分表是把双刃剑:它解决了容量与性能问题,却引入了复杂度。在决定拆分之前,先确认是否已经把单库优化到极致。
1.1 什么指标说明该拆了
瓶颈类型
常见阈值
说明
单表数据量
5000 万 ~ 1 亿行
InnoDB B+Tree 层级变深,范围查询变慢
单库数据量
500 GB ~ 1 TB
备份、恢复、迁移成本陡增
单库连接数
80% max_connections
应用池化再好也会被打满
单库写 TPS
CPU / IO 长期 80%+
索引维护、redo log、锁竞争放大
1.2 拆分前的三板斧
SQL 与索引优化:慢查询、索引失效、大事务往往是真正元凶,详见 MySQL 索引优化专题。
读写分离:把读流量拆到从库,主库只负责写,成本比分片低得多。
缓存与归档:热数据放 Redis,冷数据归档,能大幅推迟拆分 ...
“线上读写都在一台 MySQL,CPU 飙到 90% 怎么办?””主库挂了,多久能切换?”主从复制和读写分离是 MySQL 横向扩展与容灾的必经之路。本文从复制原理到生产落地一次性讲透。
一、为什么需要主从复制单节点 MySQL 同时承担读和写时,随着流量增长,很快会碰到三大瓶颈:
瓶颈
表现
影响
读压力
查询量过大,CPU/内存/IO 飙升
影响写入稳定性
可用性
单点故障导致整个业务不可用
RTO 无法保证
备份
在业务库上直接做全量备份
锁表、抖动、影响线上
主从复制(Replication)把主库(Master)的数据实时同步到一个或多个从库(Slave),做到:
读扩展:把读流量分散到从库。
高可用:主库故障时,从库可快速切换。
离线备份:在从库上做备份、归档、报表,不打扰主库。
二、复制依赖:binlog 与 relay logMySQL 复制本质上是基于 binlog 的逻辑日志复制。主库把变更记录到 binlog,从库读取并重放。
2.1 binlog 的三种格式
格式
记录内容
优点
缺点
适用场景
STATEME ...
“我用的是 RR 隔离级别,为什么还是出现了幻读?””两个事务各更新一行,结果直接死锁了?”事务和锁是 MySQL 里最容易翻车、也最常被面试官追问的部分。本文从原理到实战一次讲透,建议收藏对照。
一、为什么需要事务没有事务时,一组操作要么全部成功、要么全部失败就无法保证。典型场景:账户 A 给账户 B 转账 100 元,需要执行「A 扣 100」「B 加 100」两条 SQL。如果在两条语句之间数据库宕机,就会出现 A 的钱扣了、B 的钱没加的数据不一致。
事务(Transaction)的作用,就是把多个操作打包成一个不可分割的整体,保证业务的正确性。
二、事务的四大特性:ACID
特性
含义
InnoDB 如何实现
Atomicity 原子性
事务内的操作要么全做、要么全不做
undo log(回滚日志)
Consistency 一致性
事务前后数据都满足业务约束
由 A、I、D 共同保证
Isolation 隔离性
并发事务之间互不影响
锁 + MVCC
Durability 持久性
提交后数据永久保存
redo log(重做日志)
2.1 原 ...
“我明明建了索引,为什么还是全表扫描?”这是 MySQL 优化里最常遇到的问题。索引失效的原因很多,但归根结底就两大类:写法让索引没法用,或者优化器算完账觉得不用更快。本文把两类都拆开讲。
一、先搞懂 InnoDB 的索引结构不理解 B+Tree,就记不住那些失效规则,只能死记硬背。
1.1 为什么是 B+Tree 而不是 BTree
对比项
BTree
B+Tree
数据存储位置
每个节点都存数据
只有叶子节点存数据
叶子节点连接
无
有双向链表相连
单点查询性能
可能更快(根附近就命中)
稳定,都要走到叶子
范围查询
需要中序遍历
沿链表顺序扫描,极快
非叶子节点容量
小(要存数据)
大(只存键值),树更矮
B+Tree 的优势集中在一句话上:非叶子节点不存数据,所以一个页能装下更多键值,树高更矮,磁盘 IO 次数更少。
粗略估算:InnoDB 默认页大小 16 KB,主键为 bigint(8 字节)+ 指针(6 字节)约 14 字节,一个非叶子页能放约 1170 个键值。
树高 2 层:约 1170 × 16 ≈ 1.8 万行
树高 3 ...






























