2. 数据库基础回顾:关系型与非关系型数据库选型、连接池配置、事务隔离级别
2.1 关系型与非关系型数据库选型
在构建高并发、高可用的后端系统时,数据库选型是架构设计的基石。关系型数据库(RDBMS)与非关系型数据库(NoSQL)并非对立关系,而是互补的存储策略。选型的核心依据是数据一致性要求、访问模式以及扩展性需求。
选型黄金法则: 核心业务数据(订单、账户、用户)优先使用关系型数据库;高并发缓存、会话管理、时序数据、图关系数据优先使用非关系型数据库。
2.1.1 核心特性对比
| 维度 | 关系型数据库(MySQL / PostgreSQL) | 非关系型数据库(Redis / MongoDB / Cassandra) |
|---|---|---|
| 数据模型 | 结构化表、行、列,严格 Schema | 键值、文档、列族、图,灵活 Schema |
| 事务支持 | ACID 强事务,支持复杂多行操作 | BASE 最终一致性,部分支持有限事务 |
| 扩展方式 | 垂直扩展为主,读写分离、分库分表 | 水平扩展原生支持,自动分片 |
| 查询能力 | SQL 标准,JOIN、子查询、聚合 | API 驱动,简单查询,部分支持类 SQL |
| 典型场景 | 金融、ERP、CRM、订单系统 | 缓存、会话、日志、IoT、社交图谱 |
2.1.2 选型决策流程
以下决策树可以帮助团队快速定位合适的数据库类型:
- 数据是否需要强事务(ACID)? → 是:选择关系型数据库;否:进入下一步。
- 数据模型是否固定且关联复杂? → 是:选择关系型数据库;否:进入下一步。
- 主要访问模式是否基于 Key 查询? → 是:选择键值存储(Redis);否:进入下一步。
- 数据是否为文档型且 Schema 多变? → 是:选择文档数据库(MongoDB);否:进入下一步。
- 是否需要存储时间序列或海量日志? → 是:选择列族数据库(Cassandra / InfluxDB)。
架构实践: 现代微服务架构中,推荐采用混合持久化策略。例如:订单服务使用 MySQL 保证资金安全,商品详情服务使用 MongoDB 应对多变属性,热点数据使用 Redis 缓存加速。
2.2 连接池配置
数据库连接池是后端系统性能优化的关键组件。频繁创建和销毁数据库连接的开销极大,连接池通过复用一组已建立的连接,显著降低延迟和资源消耗。
2.2.1 核心参数配置
| 参数名称 | 推荐值 | 说明 |
|---|---|---|
| initialSize | 5 ~ 10 | 初始化时创建的连接数,应对突发流量 |
| maxActive | 20 ~ 50 | 最大活跃连接数,受数据库 max_connections 限制 |
| minIdle | 5 ~ 10 | 最小空闲连接数,避免频繁创建连接 |
| maxWait | 3000 ~ 5000 ms | 获取连接的超时时间,防止线程阻塞 |
| timeBetweenEvictionRunsMillis | 60000 ms | 空闲连接回收检查周期 |
| testWhileIdle | true | 空闲时验证连接有效性,避免连接失效 |
2.2.2 连接池配置示例(HikariCP)
# HikariCP 推荐配置(Spring Boot 环境)
spring.datasource.hikari.connection-timeout=3000
spring.datasource.hikari.maximum-pool-size=30
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.validation-timeout=1000
连接池配置陷阱:
- maxActive 过大:数据库连接数耗尽,导致其他服务无法连接。
- maxWait 过小:高并发时频繁抛出连接超时异常。
- 未配置 testWhileIdle:空闲连接被数据库回收后,应用仍在使用,导致连接失效。
- maxLifetime 超过数据库连接超时时间:连接被数据库强制断开,应用层报错。
2.3 事务隔离级别
事务隔离级别决定了并发事务之间的可见性和相互影响程度。隔离级别越高,数据一致性越强,但并发性能越低。理解隔离级别是设计高并发数据安全策略的前提。
2.3.1 四种隔离级别对比
| 隔离级别 | 脏读 | 不可重复读 | 幻读 | 实现机制 |
|---|---|---|---|---|
| READ UNCOMMITTED | 可能 | 可能 | 可能 | 不加锁,直接读取 |
| READ COMMITTED | 避免 | 可能 | 可能 | 行级锁 + 快照读 |
| REPEATABLE READ | 避免 | 避免 | 可能(InnoDB 通过间隙锁避免) | 行级锁 + 间隙锁 + MVCC |
| SERIALIZABLE | 避免 | 避免 | 避免 | 表级锁 / 谓词锁 |
2.3.2 隔离级别选型建议
- READ COMMITTED:大多数业务系统的默认选择,平衡一致性与性能。适用于订单、支付等核心交易场景。
- REPEATABLE READ:MySQL InnoDB 默认级别,适合需要多次读取同一数据且要求一致的场景(如报表统计)。
- SERIALIZABLE:仅用于对数据一致性要求极高的场景(如金融对账),并发性能极低。
- READ UNCOMMITTED:几乎不使用,脏读风险过高。
实践建议: 在微服务架构中,建议将事务隔离级别统一设置为 READ COMMITTED,并通过应用层的乐观锁(版本号)或分布式锁来解决并发冲突,避免依赖数据库高隔离级别带来的性能损耗。
2.4 本章小结
- 数据库选型:根据数据一致性、模型复杂度、访问模式选择 RDBMS 或 NoSQL,推荐混合持久化架构。
- 连接池配置:合理设置 maxActive、maxWait、testWhileIdle 等参数,避免连接耗尽和超时。
- 事务隔离级别:READ COMMITTED 是大多数业务的最佳平衡点,REPEATABLE READ 适用于 MySQL 默认场景,SERIALIZABLE 仅用于极端一致性需求。