线程池解决了”怎么管理线程”的问题,但线程池本身并不保证线程安全——它只是把任务交给线程执行。真正保证多线程正确协作的,是 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 ...
Redis 大多数人都”会用”,但线上事故往往出在选型和边界情况上:一个 KEYS * 拖垮整个实例,一次缓存雪崩打穿数据库。本文不讲安装,只讲生产环境真正会遇到的问题。
一、数据结构怎么选选错数据结构的代价,往往是内存翻几倍、或者用一堆笨拙的组合去模拟本该原生支持的能力。
1.1 五种基础类型对比
类型
底层实现
典型场景
单键建议上限
String
SDS 动态字符串
缓存、计数器、分布式锁、Session
值不超过 10 KB
Hash
压缩列表 / 哈希表
对象存储(购物车、用户资料)
field 不超过 1000
List
快速链表
消息队列、最新列表、粉丝列表
元素不超过 1 万
Set
哈希表 / 整数集合
去重、标签、共同好友、抽奖
元素不超过 1 万
ZSet
跳表 + 哈希表
排行榜、延迟队列、优先级队列
元素不超过 1 万
1.2 容易被忽略的选型细节String 存对象 vs Hash 存对象很多人图省事直接把对象序列化成 JSON 塞进 String:
1SET user:1001 '{"n ...
用过 Spring Boot 的人都知道”引入依赖就能用”,但一旦要自己封装一个公共组件给团队复用,就必须搞懂自动装配。本文从源码层面拆开 @SpringBootApplication,然后带你手写一个能放进生产环境的 Starter。
一、自动装配到底做了什么1.1 从 @SpringBootApplication 拆起每个 Spring Boot 项目的启动类上都挂着这么一个注解:
123456@SpringBootApplicationpublic class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}
它其实是一个”三合一”的组合注解,扒开源码能看到:
12345678@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@SpringBootConfiguration ...
经验分享
未读下载node.js点击此处下载结果如下图:
双击点击下载的pkg[根据下图步骤依次点击即可]
选择合适的存储位置安装完成之后检验是否成功
黑窗口输入node -v






























