1. 首页 > 国产数据库教程 > openGauss教程 > 正文

opengauss教程FG063-openGauss读写分离配置生产实战

本文档详细介绍openGauss数据库读写分离的配置方法,包括应用层、中间件层、代理层等多种实现方式,风哥教程参考openGauss官方文档高可用架构指南、应用开发指南等内容,适合DBA和开发人员进行读写分离配置时参考。

Part01-基础概念与理论知识

1.1 openGauss读写分离基本概念

openGauss读写分离优势:

  • 提升读性能:多个备库分担读请求,提升系统读吞吐量
  • 减轻主库压力:将读操作从主库转移到备库
  • 提高可用性:单点故障时读操作可切换到其他备库
  • 扩展性强:可以增加备库数量线性扩展读性能

1.2 openGauss读写分离实现方式

读写分离的三种实现方式:

# 读写分离实现方式

1. 应用层实现
– 在应用程序代码中实现读写分离逻辑
– 优点:灵活可控,可以根据业务定制
– 缺点:需要修改应用代码,维护成本高

2. 中间件层实现
– 使用数据库中间件(如ShardingSphere、MyCat)
– 优点:对应用透明,集中管理
– 缺点:增加系统复杂度,可能成为性能瓶颈

3. 代理层实现
– 使用数据库代理(如Pgpool-II、HAProxy)
– 优点:对应用完全透明,支持连接池
– 缺点:需要额外部署代理服务

三种方式对比:
方式 | 复杂度 | 性能 | 灵活性 | 维护成本
————–|——–|——|——–|———-
应用层 | 中 | 高 | 高 | 高
中间件层 | 高 | 中 | 中 | 中
代理层 | 低 | 中 | 低 | 低

1.3 openGauss读写分离一致性问题

读写分离面临的主要问题是一致性问题:

# 读写分离一致性问题

1. 复制延迟导致的数据不一致
场景:
T1: 主库执行 INSERT INTO fgedu.users VALUES (1, ‘test’)
T2: 应用立即查询备库 SELECT * FROM fgedu.users WHERE id=1
结果:查询不到数据(复制延迟)

2. 解决方案
a) 强制走主库
– 对一致性要求高的查询强制走主库
– 实现:在SQL中添加hint或配置规则

b) 延迟检测
– 查询前检查复制延迟
– 延迟超过阈值则走主库

c) 会话绑定
– 同一会话的写操作后的读操作走主库
– 实现:在应用中维护会话状态

d) 业务补偿
– 接受短暂的数据不一致
– 通过业务逻辑处理不一致情况

3. 一致性级别
– 强一致性:所有读操作走主库
– 最终一致性:允许短暂延迟,最终数据一致
– 弱一致性:接受一定程度的延迟

Part02-生产环境规划与建议

2.1 openGauss读写分离架构设计

读写分离架构设计:

# 读写分离架构设计

架构一:应用层读写分离
+—————-+ +——————+
| 应用服务器 | | 应用服务器 |
| (读写分离逻辑) | | (读写分离逻辑) |
+——–+——-+ +——–+———+
| |
+———–+———–+
|
+————-+————-+
| |
+——v——-+ +——–v——-+
| 主库 | | 备库 |
| (写操作) | | (读操作) |
| 192.168.1.10 | | 192.168.1.11 |
+————–+ +—————-+

架构二:中间件层读写分离
+—————-+ +——————+
| 应用服务器 | | 应用服务器 |
| (统一连接串) | | (统一连接串) |
+——–+——-+ +——–+———+
| |
+———–+———–+
|
+———-v———-+
| ShardingSphere |
| (读写分离中间件) |
+———-+———-+
|
+————-+————-+
| |
+——v——-+ +——–v——-+
| 主库 | | 备库 |
| (写操作) | | (读操作) |
+————–+ +—————-+

架构三:代理层读写分离
+—————-+ +——————+
| 应用服务器 | | 应用服务器 |
| (连接代理) | | (连接代理) |
+——–+——-+ +——–+———+风哥提示:
| |
+———–+———–+
|
+———-v———-+
| Pgpool-II |
| (数据库代理) |
+———-+———-+
|
+————-+————-+
| |
+——v——-+ +——–v——-+
| 主库 | | 备库 |
| (写操作) | | (读操作) |
+————–+ +—————-+

2.2 openGauss负载均衡策略

负载均衡策略:

# 负载均衡策略

1. 轮询(Round Robin)
– 按顺序将读请求分发到各备库
– 优点:简单公平
– 缺点:不考虑备库性能差异

2. 权重(Weighted)
– 根据备库性能设置权重
– 优点:考虑性能差异
– 缺点:需要动态调整权重学习交流加群风哥微信: itpux-com

3. 最小连接数(Least Connections)
– 将请求分发到当前连接数最少的备库
– 优点:动态负载均衡
– 缺点:需要实时监控连接数

4. 随机(Random)
– 随机选择备库
– 优点:实现简单
– 缺点:可能不均衡

5. 一致性哈希(Consistent Hashing)
– 根据查询条件哈希选择备库
– 优点:相同查询走同一备库,利于缓存
– 缺点:实现复杂

# 推荐配置
– 同配置备库:使用轮询
– 不同配置备库:使用权重
– 高并发场景:使用最小连接数

2.3 openGauss延迟处理策略

延迟处理策略:

# 延迟处理策略

1. 延迟检测
– 定期检测备库复制延迟
– 延迟超过阈值将该备库从读列表中移除

2. 延迟阈值设置
– 一般业务:延迟<1秒 - 关键业务:延迟<100毫秒 - 实时业务:延迟<10毫秒 3. 延迟处理 - 延迟超限:读请求转发到其他备库或主库 - 延迟恢复:自动将该备库重新加入读列表 4. 延迟监控脚本学习交流加群风哥QQ113257174 #!/bin/bash # check_replication_delay.sh # from:www.itpux.com.qq113257174.wx:itpux-com # web: `http://www.fgedu.net.cn` MASTER_IP="192.168.1.10" THRESHOLD=1000 # 延迟阈值1秒 echo "=== 复制延迟检查 ===" echo "检查时间: $(date)" # 检查各备库延迟 gsql -h $MASTER_IP -d postgres -c " SELECT application_name, client_addr, EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) * 1000 as delay_ms FROM pg_stat_replication WHERE EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) * 1000 > $THRESHOLD;
” | while read line; do
echo “告警: 备库延迟超过阈值 – $line”
# 发送告警通知
# echo “$line” | mail -s “复制延迟告警” dba@fgedu.net.cn
done

echo “=== 检查完成 ===”

Part03-生产环境项目实施方案

3.1 openGauss应用层读写分离

3.1.1 Java应用读写分离配置

# Java应用读写分离配置(Spring Boot)

# application.yml更多视频教程www.fgedu.net.cn
spring:
datasource:
master:
driver-class-name: org.opengauss.Driver
jdbc-url: jdbc:opengauss://192.168.1.10:5432/fgedudb
username: fgedu
password: fgedu_pass
hikari:
maximum-pool-size: 20
minimum-idle: 5
slave:
driver-class-name: org.opengauss.Driver
jdbc-url: jdbc:opengauss://192.168.1.11:5432/fgedudb
username: fgedu
password: fgedu_pass
hikari:
maximum-pool-size: 50
minimum-idle: 10

# 读写分离配置类
@Configuration
public class DataSourceConfig {

@Bean
@ConfigurationProperties(“spring.datasource.master”)
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}

@Bean
@ConfigurationProperties(“spring.datasource.slave”)
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}

@Bean
public DataSource routingDataSource() {
DynamicRoutingDataSource routingDataSource = new DynamicRoutingDataSource();
Map targetDataSources = new HashMap<>();更多学习教程公众号风哥教程itpux_com
targetDataSources.put(“master”, masterDataSource());
targetDataSources.put(“slave”, slaveDataSource());
routingDataSource.setTargetDataSources(targetDataSources);
routingDataSource.setDefaultTargetDataSource(masterDataSource());
return routingDataSource;
}
}

# 使用注解切换数据源
@Service
public class FgeduUserService {

@Autowired
private JdbcTemplate jdbcTemplate;

@WriteOperation # 走主库
public void insertUser(FgeduUser user) {
String sql = “INSERT INTO fgedu.users (id, name, create_time) VALUES (?, ?, ?)”;
jdbcTemplate.update(sql, user.getId(), user.getName(), new Date());
}

@ReadOperation # 走备库
public List queryUsers() {
String sql = “SELECT * FROM fgedu.users”;
return jdbcTemplate.query(sql, new UserRowMapper());
}
}

3.2 openGauss中间件读写分离

from DB视频:www.itpux.com

3.2.1 ShardingSphere读写分离配置

# ShardingSphere读写分离配置

# application.yml
spring:
shardingsphere:
datasource:
names: master,slave0,slave1
master:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: org.opengauss.Driver
jdbc-url: jdbc:opengauss://192.168.1.10:5432/fgedudb
username: fgedu
password: fgedu_pass
slave0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: org.opengauss.Driver
jdbc-url: jdbc:opengauss://192.168.1.11:5432/fgedudb
username: fgedu
password: fgedu_pass
slave1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: org.opengauss.Driver
jdbc-url: jdbc:opengauss://192.168.1.12:5432/fgedudb
username: fgedu
password: fgedu_pass

masterslave:
name: ms_ds
master-data-source-name: master
slave-data-source-names: slave0,slave1
load-balance-algorithm-type: round_robin # 轮询负载均衡

props:
sql.show: true

# 使用方式(对应用透明)
@Service
public class FgeduOrderService {

@Autowired
private JdbcTemplate jdbcTemplate;

# 写操作自动走主库
public void createOrder(FgeduOrder order) {
String sql = “INSERT INTO fgedu.orders (order_id, user_id, amount) VALUES (?, ?, ?)”;
jdbcTemplate.update(sql, order.getOrderId(), order.getUserId(), order.getAmount());
}

# 读操作自动走备库(轮询)
public List queryOrders(Long userId) {
String sql = “SELECT * FROM fgedu.orders WHERE user_id = ?”;
return jdbcTemplate.query(sql, new OrderRowMapper(), userId);
}
}

# 启动日志
INFO [main] o.a.s.core.log.ConfigurationLogger : MasterSlaveRuleConfiguration
masterDataSourceName: master
slaveDataSourceNames: [slave0, slave1]
loadBalanceAlgorithmType: round_robin

3.3 openGauss代理层读写分离

3.3.1 Pgpool-II读写分离配置

# Pgpool-II读写分离配置

# 步骤1:安装Pgpool-II
$ yum install pgpool-II pgpool-II-extensions

# 步骤2:配置pgpool.conf
$ cat > /etc/pgpool-II/pgpool.conf << EOF # 基本配置 listen_addresses = '*' port = 9999 socket_dir = '/tmp' # 后端数据库配置 backend_hostname0 = '192.168.1.10' backend_port0 = 5432 backend_weight0 = 0 backend_data_directory0 = '/opengauss/fgdata' backend_flag0 = 'ALWAYS_MASTER' backend_hostname1 = '192.168.1.11' backend_port1 = 5432 backend_weight1 = 1 backend_data_directory1 = '/opengauss/fgdata' backend_flag1 = 'ALLOW_TO_FAILOVER' backend_hostname2 = '192.168.1.12' backend_port2 = 5432 backend_weight2 = 1 backend_data_directory2 = '/opengauss/fgdata' backend_flag2 = 'ALLOW_TO_FAILOVER' # 读写分离配置 load_balance_mode = on master_slave_mode = on master_slave_sub_mode = 'stream' # 负载均衡配置 backend_weight0 = 0 # 主库权重为0,只处理写操作 backend_weight1 = 1 # 备库1权重 backend_weight2 = 1 # 备库2权重 # 健康检查配置 health_check_period = 10 health_check_timeout = 20 health_check_user = 'fgedu' health_check_password = 'fgedu_pass' # 连接池配置 max_pool = 4 num_init_children = 32 max_connections = 0 EOF # 步骤3:配置pcp.conf(管理用户) $ echo 'fgedu_admin:md5加密密码' >> /etc/pgpool-II/pcp.conf

# 步骤4:配置pool_hba.conf
$ cat > /etc/pgpool-II/pool_hba.conf << EOF local all all md5 host all all 127.0.0.1/32 md5 host all all 192.168.1.0/24 md5 EOF # 步骤5:启动Pgpool-II $ pgpool -n -D # 步骤6:验证配置 $ psql -h 192.168.1.10 -p 9999 -U fgedu -d fgedudb -c "SHOW pool_nodes;

node_id | hostname | port | status | lb_weight | role
———+————–+——+——–+———–+———
0 | 192.168.1.10 | 5432 | up | 0.000000 | primary
1 | 192.168.1.11 | 5432 | up | 0.500000 | standby
2 | 192.168.1.12 | 5432 | up | 0.500000 | standby
(3 rows)

# 应用连接方式
# 应用只需连接Pgpool-II,读写分离对应用完全透明
jdbc-url: jdbc:opengauss://192.168.1.10:9999/fgedudb

Part04-生产案例与实战讲解

4.1 openGauss Java应用读写分离案例

4.1.1 案例背景

某电商平台使用Spring Boot开发,需要实现读写分离提升读性能。

4.1.2 完整配置

# 完整Java读写分离配置

# 1. 数据源配置
@Configuration
public class FgeduDataSourceConfig {

@Primary
@Bean(“masterDataSource”)
@ConfigurationProperties(prefix = “spring.datasource.master”)
public DataSource masterDataSource() {

本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html

联系我们

在线咨询:点击这里给我发消息

微信号:itpux-com

工作日:9:30-18:30,节假日休息