目录
当数据库遭遇流量洪峰,传统「垂直扩容」如同不断给老旧卡车更换更大发动机——成本指数级增长,性能却线性提升。面对水平扩展困局,业界通常采用两种方案:一是分库分表中间件,通过ShardingSphere/MyCat等工具将数据人工分片到多个MySQL实例,如同把图书馆拆分成数十个小书摊,按用户ID哈希或地域规则分配数据,适合存量系统改造且分片逻辑清晰的场景,但跨分片查询如同让读者跑遍全城书摊找齐一套百科全书;二是原生分布式数据库,以OceanBase/TiDB为代表,如同建造智能立体书库,业务无需感知数据自动分片,添加节点如同扩展书架层数,尤其适合新业务直接构建分布式架构或需要高频跨节点关联查询的场景。
技术演进正如内燃机向电动机转型,云原生时代分布式数据库正从「备选方案」升级为「默认基建」,分库分表中间件逐渐退守为过渡期兼容层,而金融、政务等强一致性场景已全面转向Paxos/Raft系数据库。
本文将聚焦第二种方案的实战落地,以OceanBase官方文档为蓝本,提炼核心要点,前4章节侧重于理论,后3章节侧重实践,帮助开发者跨越从「知道」到「做到」的鸿沟。
1. 系统架构
OceanBase是分布式集群架构,各个节点之间完全对等,下图在官方架构图的基础上标注了核心名词解释,便于大家图文结合快速理解核心概念。
2. 核心优势
2.1. 原生分布式架构
-
无限水平扩展:通过分片(Tablet)和动态负载均衡,支持数据与计算能力的线性扩展,轻松应对PB级数据和高并发场景。
-
多副本强一致:基于Paxos协议的多副本同步(默认3副本),保障RPO=0(零数据丢失),RTO<30秒(快速恢复)。
2.2. HTAP 融合引擎
-
事务与分析一体化:同一引擎支持OLTP(高并发事务)和OLAP(复杂分析),避免传统架构中ETL链路带来的延迟与复杂度。
-
智能优化器:根据负载自动选择行存(OLTP优化)或列存(OLAP优化),资源隔离减少相互干扰。
2.3. 企业级高可用性
-
多级容灾设计:
-
Zone级容灾:数据跨机房/地域分布,单机房故障自动切换。
-
节点级自愈:节点宕机时,Paxos协议秒级切换主副本,无需人工介入。
-
-
在线平滑升级:支持滚动升级,业务无感知。
2.4. 多租户与资源隔离
-
租户即服务:通过资源单元(Unit)和资源池(Resource Pool)实现CPU、内存、IO的物理隔离,支持 SaaS 化多租户场景。
-
弹性扩缩容:资源单元可在线迁移,按需分配,避免资源浪费。
2.5. 高兼容性与低成本
-
生态兼容:兼容 MySQL 和 Oracle 模式,降低迁移成本。
-
存储成本优化:基于 LSM-Tree 的存储引擎,支持高压缩率(通常 3~5 倍),节省存储开销。
2.6. 全栈自研与开源
-
自主可控:核心代码自研,无第三方数据库依赖,满足国产化需求。
-
开源开放:核心代码开源,社区驱动迭代,支持定制化扩展。
3. 对比传统数据库的突破
维度 | 传统数据库(如Oracle) | OceanBase |
---|---|---|
扩展性 | 垂直扩展(Scale-Up),成本高 | 水平扩展(Scale-Out),线性增长 |
可用性 | 依赖主备同步,RPO/RTO分钟级 | 多副本强一致,RPO=0,RTO秒级 |
成本 | 商业授权费高,存储无压缩 | 开源+存储压缩,成本降低50%~80% |
HTAP支持 | 需分离OLTP/OLAP系统 | 单引擎支持,实时分析 |
4. 适用场景
金融级核心系统:高可用、强一致、数据零丢失。
大型 SaaS 平台:多租户隔离、弹性资源分配。
实时数仓:HTAP能力支持交易与分析融合。
云原生应用:容器化部署、跨云多活。
5. 15分钟极速部署(Docker实战)
以Windows为例,通过容器快速安装OB用于学习研究。
5.1. 安装Docker Desktop并设置镜像加速
安装后配置镜像加速:
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": false,
"features": {
"buildkit": true
},
"registry-mirrors": [
"https://registry.docker-cn.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn",
"https://cr.console.aliyun.com",
"https://mirror.ccs.tencentyun.com"
]
}
5.2. 下载OB镜像并启动容器
a. docker命令:
docker run -p 2881:2881 --name obstandalone -e MODE=MINI -e OB_TENANT_PASSWORD=你的用户密码 -d quay.io/oceanbase/oceanbase-ce
(--name用于设置Docker容器名称,这里设置为obstandalone
-e 用于设置环境变量,示例中MODE用于设置OceanBase数据库的启动模式为mini,OB_TENANT_PASSWORD用于设置OceanBase数据库中root@test的用户密码,创建的用户租户名默认为test
)
b. 在Docker Desktop命令行输入上面的docker命令:
6. 客户端连接OB
以Navicat为例,从官网可知16.1.2版本起支持OB社区版,我们可以下载该版本连接OB,如果是较低版本使用“新建MySQL连接”也能正常连上。另外,OB社区版仅支持MySQL模式。
以Navicat 17为例,新建连接,使用root@test,密码为上面5.2.docker命令中OB_TENANT_PASSWORD设置的密码:
7. 应用开发
以上面第5点安装的OB社区版为例,因为完全兼容MySQL协议,可以直接使用标准的MySQL JDBC驱动,使用SpringBoot+Mybatis连接OB社区版(MySQL模式)跟我们以往使用MySQL数据库搭建项目没有差异,application.yml中spring.datasource.url连接信息填写OB的连接信息即可:
spring:
application:
name: springboot-demo
main:
allow-bean-definition-overriding: true
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:2881/test?useSSL=false&serverTimezone=UTC
username: root@test
password: admin
server:
port: 8080
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>springboot-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-demo</name>
<description>springboot-demo</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.5.4</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- spring web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<!-- Lombok (可选) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>com.example.demo.SpringbootDemoApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
单元测试类测试查询表:
package com.example.demo;
import com.alibaba.fastjson.JSON;
import com.example.demo.infrastructure.dao.UserDao;
import com.example.demo.infrastructure.po.User;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* OceanBase-单元测试类
*/
@SpringBootTest
@Slf4j
public class OceanBaseQueryTest {
@Resource
UserDao userDao;
/**
* 测试查询用户信息
*/
@Test
public void testQueryUser() {
User user = userDao.findById(1);
log.info("查询OceanBase User表结果={}", JSON.toJSONString(user));
assertNotNull(user);
}
}
单侧运行结果: