数据库死锁
死锁本质定义:两个或多个事务因抢夺资源形成互相等待的僵局,可用火锅抢餐具的场景类比理解。
转账场景还原:设置账户一、账户二,事务 a 转账户一资金到账户二,事务 b 转账户二资金到账户一;事务 a 先锁住账户一,事务 b 随即锁住账户二。
死锁闭环形成:事务 a 需操作被事务 b 锁住的账户二,只能等待;事务 b 需操作被事务 a 锁住的账户一,也只能等待,二者形成互相等待的死锁闭环。
数据库解决机制:数据库存储引擎的死锁检测机制会识别死锁,计算并强制回滚代价较小的事务,让另一事务顺利执行。
程序员小哲以下单逻辑重构为例,讲解 DDD 领域驱动设计的核心逻辑与应用优势。
传统写法问题:多数程序员写下单系统时,以增删改查思维构建,将订单创建、支付、取消等逻辑塞进庞大的 Service 类,业务规则分散在服务层、控制器等各处,修改规则需全局搜索,易出 bug。
DDD 核心思路:DDD 核心是将业务概念转化为带行为的领域对象,让订单这类核心对象自行管理业务规则,比如订单自行判断能否支付、取消,状态变更由自身掌控。
重构后变化:重构后 Service 层仅负责协调,只需找到订单对象并触发其对应动作,再保存数据,业务规则收敛到领域对象内,代码可读性和可维护性大幅提升。
DDD 适用场景:DDD 适用于包含订单、账户、风控等的复杂业务,或微服务拆分场景,它按业务边界拆分,而非拍脑袋定微服务。
视频最后提出思考题:优惠券抵扣逻辑在 DDD 视角下应放在哪个对象里。
视频讲解了 Redis 除缓存外的 8 种高级应用场景及实现逻辑。
布隆过滤器:用于解决缓存击穿问题,通过三个哈希函数映射二进制位判断数据是否存在,1 亿个 ID 仅占用极少内存,仅存 0 和 1,存在一定误差但能高效处理海量布尔统计。
分布式锁:保障分布式架构并发安全,同一时间仅一个线程可获取锁,自带看门狗机制,能为长任务锁续命,避免锁过期导致数据混乱。
延迟队列:替代定时任务处理批量数据,将任务触发时间作为 score 存入 ZSET,自动按时间排序,到点自动弹出,兼顾性能与秒级精准度。
流量限流:通过令牌桶机制应对突发流量,Redis 匀速生产令牌,桶空时请求丢弃或排队,平滑处理请求避免系统雪崩。
HyperLogLog(状态统计):用于用户签到、在线状态等场景,将海量布尔状态压缩至每个用户 1bit 位,支持秒级位运算,节省内存。
HyperLogLog(UV 统计):用于页面独立访客去重统计,采用概率算法,固定占用 12kb 内存,存在 0.81 的微小误差,适合只求总数的场景。
Geo 位置计算:实现附近的人、骑手距离查询,将二维地图转化为直线做范围搜索,是外卖、打车调度的底层技术。
轻量级 MQ:通过 Redis Stream 实现,支持消费者组、消息回溯、ACK 和持久化,保证消息不丢失,拥有内存级读写性能,适合中小规模消息业务。
视频讲解了 Java 中 AQS 的定义、核心功能及独占、共享两种模式的区别。
AQS 基础定义:AQS 全称 AbstractQueuedSynchronizer,是 JUC 包中的抽象类,是 ReentrantLock、CountDownLatch 等 JUC 并发工具的底层实现基石。
核心功能 1:管 state:AQS 管理被 volatile 修饰的 state 变量,该变量可作为锁标记或资源计数器,线程能否访问资源由子类定义的 state 操作规则决定。
核心功能 2:维护等待队列:AQS 维护线程等待队列,拿不到资源的线程会进入队列阻塞,待资源释放后按规则被唤醒。
独占模式说明:将 state 视为 0 或 1 的开关,0 代表无线程占用资源,1 代表已被占用,仅允许单个线程独享资源;释放资源时仅唤醒队列下一个线程。
共享模式说明:将 state 视为资源计数器,值代表剩余资源量,只要 state 大于 0 线程即可领取;释放资源时可唤醒一连串等待线程。
视频讲解了大厂 MySQL 面试中 "超过三张表禁止使用 join" 的底层逻辑与替代方案。
性能大坑解析:MySQL 多表 join 采用 NLJ 算法,类似多层嵌套 for 循环,三张大数据表 join 时时间复杂度呈指数级增长,会导致数据库 CPU 飙升至 100%,还会挤走数据库缓存中的热业务数据,拖垮数据库。
架构死局说明:互联网业务数据量增长快,后续需分库分表,分库分表后表会分布在不同机器,数据库无法跨机器执行 join 操作,前期写满多表 join 的代码需全部重写,产生沉重技术债务。
内存组装方案:数据库资源宝贵且难横向扩容,应用服务器易扩容,大厂将多表 join 拆解为多次单表查询,在应用服务器内存中组装数据,把计算压力从数据库转移到应用服务器,符合高可用架构原则。
视频最后提出思考题:代码内存组装数据量过大时是否会内存溢出及如何处理。
MySQL 中存储为 char 类型的带尾部空格的 abc 与 varchar 类型的无空格 abc 的相等性受配置影响。
存储本质差异:char 为定长存储,存储 abc 时底层会补空格;varchar 为变长存储,存储 abc 时无空格。
默认配置判定:MySQL 默认配置下,二者比较结果为相等,原因是 MySQL 比较字符串时会自动忽略 char 尾部的空格。
SQL 模式影响:开启 PAD_CHAR_TO_FULL_LENGTH 模式后,仅会让查询 char 类型长度时返回定义长度,不会改变比较规则,二者仍相等。
排序规则作用:排序规则的 PAD 属性才是关键,默认 PAD_SPACE 属性下二者相等;改为 utf8mb4_0900_ai_ci 这类 NO_PAD 属性的排序规则后,char 尾部空格生效,二者不再相等。
该内容可帮助 Java 后端开发者应对相关面试问题。