yashandb教程FG044-YashanDB读写分离配置
本文档风哥主要介绍YashanDB读写分离配置相关知识,包括YashanDB读写分离概念、原理、优势、架构设计、策略、负载均衡器部署、读写分离配置、应用适配、实战案例、最佳实践等内容,风哥教程参考YashanDB官方文档高可用与容灾内容编写,适合DBA人员在学习和测试中使用,如果要应用于生产环境则需要自行确认。更多视频教程www.fgedu.net.cn
Part01-基础概念与理论知识
1.1 YashanDB读写分离概念
YashanDB读写分离是指将数据库的读操作和写操作分离到不同的数据库节点上,写操作指向主库,读操作指向备库,从而提高系统的并发处理能力和整体性能。学习交流加群风哥微信: itpux-com
- 主库负责处理所有写操作
- 备库负责处理读操作
- 通过负载均衡器或应用层实现请求分发
- 提高系统的并发处理能力
1.2 YashanDB读写分离原理
YashanDB读写分离的工作原理:
- 主库执行写操作,生成WAL日志
- 备库通过复制主库的WAL日志保持数据同步
- 负载均衡器或应用层根据SQL语句类型将请求分发到不同节点
- 写操作发送到主库,读操作发送到备库
- 多个备库可以分担读操作压力,提高系统整体性能
1.3 YashanDB读写分离优势
YashanDB读写分离的优势:
- 提高系统性能:读操作分散到多个备库,减轻主库压力
- 提高并发能力:多个备库同时处理读请求,增加系统并发处理能力
- 提高可用性:当主库故障时,备库仍可提供读服务
- 负载均衡:读操作在多个备库之间均衡分配
- 灵活扩展:可以通过增加备库数量来提高读性能
Part02-生产环境规划与建议
2.1 YashanDB读写分离架构设计
YashanDB读写分离的架构设计:
1. 主库:处理所有写操作
2. 备库:处理读操作,可多个
3. 负载均衡器:分发请求,如PgBouncer、ProxySQL、HAProxy等
4. 应用层:根据业务逻辑分发请求
# 常见架构模式
## 模式1:基于负载均衡器的读写分离
– 负载均衡器:PgBouncer、ProxySQL、HAProxy
– 优点:配置简单,对应用透明
– 缺点:需要额外的负载均衡器组件
## 模式2:基于应用层的读写分离
– 应用层:在应用代码中实现读写分离逻辑
– 优点:灵活性高,可根据业务需求定制
– 缺点:需要修改应用代码,维护成本高
## 模式3:基于中间件的读写分离
– 中间件:如Mycat、ShardingSphere等
– 优点:功能丰富,支持多种数据库
– 缺点:增加系统复杂度,可能成为性能瓶颈
2.2 YashanDB读写分离策略
YashanDB读写分离的策略选择:
## 1. 基于SQL语句类型
– 写操作:INSERT、UPDATE、DELETE、CREATE、ALTER、DROP等
– 读操作:SELECT
## 2. 基于事务
– 事务中的所有操作都发送到主库
– 非事务操作根据类型分发
## 3. 基于会话
– 会话开始时选择节点
– 会话中的所有操作都发送到同一节点
## 4. 基于权重
– 根据备库的性能和负载设置权重
– 权重高的备库处理更多的读请求
## 5. 基于数据一致性要求
– 对数据一致性要求高的读操作发送到主库
– 对数据一致性要求不高的读操作发送到备库
2.3 YashanDB读写分离考量因素
YashanDB读写分离的考量因素:
- 数据一致性:备库数据可能存在延迟,需要考虑业务对数据一致性的要求
- 网络延迟:负载均衡器与数据库节点之间的网络延迟
- 负载均衡:如何在多个备库之间均衡分配读请求
- 故障处理:当某个备库故障时如何处理
- 应用适配:应用是否需要修改以支持读写分离
- 监控和告警:如何监控读写分离的状态和性能
Part03-生产环境项目实施方案
3.1 YashanDB负载均衡器部署
YashanDB负载均衡器的部署与配置:
## 1. 安装PgBouncer
$ dnf install -y pgbouncer
## 2. 配置PgBouncer
$ cat > /etc/pgbouncer/pgbouncer.ini << EOF
[databases]
fgedudb = host=192.168.1.100 port=5432 dbname=fgedudb
fgedudb_ro = host=192.168.1.101 port=5432 dbname=fgedudb
[pgbouncer]
listen_addr = *
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 20
min_pool_size = 5
reserve_pool_size = 10
reserve_pool_timeout = 5.0
max_db_connections = 100
max_user_connections = 50
EOF
## 3. 创建用户认证文件
$ cat > /etc/pgbouncer/userlist.txt << EOF
"fgedu" "fgedu123"
EOF
## 4. 启动PgBouncer
$ systemctl start pgbouncer
$ systemctl enable pgbouncer
## 5. 验证PgBouncer状态
$ pgbouncer -C "SHOW POOLS;"
3.2 YashanDB读写分离配置
YashanDB读写分离的具体配置:
## 1. 配置主库
$ cat >> /yashanb/fgdata/fgedudb/postgresql.conf << EOF
# 主库参数
listen_addresses = '0.0.0.0'
port = 5432
max_connections = 1000
shared_buffers = '16GB'
# 复制参数
wal_level = 'hot_standby'
max_wal_senders = 10
wal_keep_segments = 100
hot_standby = on
EOF
## 2. 配置备库
$ cat >> /yashanb/fgdata/fgedudb/postgresql.conf << EOF
# 备库参数
listen_addresses = '0.0.0.0'
port = 5432
max_connections = 1000
shared_buffers = '16GB'
# 复制参数
wal_level = 'hot_standby'
max_wal_senders = 10
wal_keep_segments = 100
hot_standby = on
EOF
## 3. 配置PgBouncer路由规则
$ cat > /etc/pgbouncer/routing_rules.ini << EOF
# 路由规则
[writes]
query = ^(INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|TRUNCATE|REINDEX|VACUUM|ANALYZE)
pool = fgedudb
[reads]
query = ^SELECT
pool = fgedudb_ro
EOF
## 4. 重启PgBouncer
$ systemctl restart pgbouncer
3.3 YashanDB应用适配
YashanDB读写分离的应用适配:
## 1. Java应用适配
// 使用Spring Boot + MyBatis实现读写分离
@Configuration
public class DataSourceConfig {
@Bean(name = “masterDataSource”)
@ConfigurationProperties(prefix = “spring.datasource.master”)
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = “slaveDataSource”)
@ConfigurationProperties(prefix = “spring.datasource.slave”)
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = “dynamicDataSource”)
public DataSource dynamicDataSource(@Qualifier(“masterDataSource”) DataSource masterDataSource,
@Qualifier(“slaveDataSource”) DataSource slaveDataSource) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map
## 2. Python应用适配
# 使用SQLAlchemy实现读写分离
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# 创建主库和备库引擎
master_engine = create_engine(‘postgresql://fgedu:fgedu123@192.168.1.100:5432/fgedudb’)
slave_engine = create_engine(‘postgresql://fgedu:fgedu123@192.168.1.101:5432/fgedudb’)
# 创建会话工厂
MasterSession = sessionmaker(bind=master_engine)
SlaveSession = sessionmaker(bind=slave_engine)
# 读写分离装饰器
def read_write_separated(func):
def wrapper(*args, **kwargs):
# 根据操作类型选择数据源
if func.__name__.startswith(‘get’) or func.__name__.startswith(‘query’):
session = SlaveSession()
else:
session = MasterSession()
try:
result = func(session, *args, **kwargs)
session.commit()
return result
except Exception as e:
session.rollback()
raise e
finally:
session.close()
return wrapper
## 3. PHP应用适配
// 使用Laravel实现读写分离
// 在config/database.php中配置
‘connections’ => [
‘mysql’ => [
‘read’ => [
‘host’ => ‘192.168.1.101’,
],
‘write’ => [
‘host’ => ‘192.168.1.100’,
],
‘sticky’ => true,
‘driver’ => ‘pgsql’,
‘database’ => ‘fgedudb’,
‘username’ => ‘fgedu’,
‘password’ => ‘fgedu123’,
‘charset’ => ‘utf8’,
‘prefix’ => ”,
],
],
Part04-生产案例与实战讲解
4.1 YashanDB基于PgBouncer的读写分离
某企业使用PgBouncer实现YashanDB读写分离,提高系统性能。
– 业务系统:电商平台
– 数据量:500GB
– 并发用户:5000
– 读请求比例:80%
– 写请求比例:20%
# 部署架构
– 主库:192.168.1.100
– 备库1:192.168.1.101
– 备库2:192.168.1.102
– PgBouncer:192.168.1.200
# 配置步骤
## 1. 配置PgBouncer
$ cat > /etc/pgbouncer/pgbouncer.ini << EOF
[databases]
fgedudb = host=192.168.1.100 port=5432 dbname=fgedudb
fgedudb_ro1 = host=192.168.1.101 port=5432 dbname=fgedudb
fgedudb_ro2 = host=192.168.1.102 port=5432 dbname=fgedudb
[pgbouncer]
listen_addr = *
listen_port = 6432
auth_type = md5
auth_file = /etc/pgbouncer/userlist.txt
pool_mode = transaction
max_client_conn = 5000
default_pool_size = 50
min_pool_size = 10
reserve_pool_size = 20
reserve_pool_timeout = 5.0
max_db_connections = 200
max_user_connections = 100
EOF
## 2. 配置路由规则
$ cat > /etc/pgbouncer/routing_rules.ini << EOF
# 路由规则
[writes]
query = ^(INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|TRUNCATE|REINDEX|VACUUM|ANALYZE)
pool = fgedudb
[reads]
query = ^SELECT
pool = fgedudb_ro1,fgedudb_ro2
EOF
## 3. 启动PgBouncer
$ systemctl start pgbouncer
## 4. 应用连接配置
# 应用连接字符串
jdbc:postgresql://192.168.1.200:6432/fgedudb
## 5. 验证读写分离
# 查看PgBouncer连接状态
$ pgbouncer -C "SHOW POOLS;"
# 测试写操作
$ psql -h 192.168.1.200 -p 6432 -U fgedu -d fgedudb -c "INSERT INTO fgedu_test (name) VALUES ('test');"
# 测试读操作
$ psql -h 192.168.1.200 -p 6432 -U fgedu -d fgedudb -c "SELECT * FROM fgedu_test;"
# 查看备库状态
$ psql -h 192.168.1.101 -U fgedu -d fgedudb -c "SELECT * FROM fgedu_test;"
4.2 YashanDB基于ProxySQL的读写分离
某企业使用ProxySQL实现YashanDB读写分离,提供更灵活的负载均衡策略。
– 业务系统:金融交易系统
– 数据量:1TB
– 并发用户:10000
– 读请求比例:90%
– 写请求比例:10%
# 部署架构
– 主库:192.168.1.100
– 备库1:192.168.1.101
– 备库2:192.168.1.102
– 备库3:192.168.1.103
– ProxySQL:192.168.1.200
# 配置步骤
## 1. 安装ProxySQL
$ dnf install -y proxysql
## 2. 配置ProxySQL
$ mysql -u admin -padmin -h 127.0.0.1 -P 6032
ProxySQLAdmin> INSERT INTO mysql_servers (hostgroup_id, hostname, port, weight, max_connections) VALUES
(10, ‘192.168.1.100’, 5432, 100, 1000),
(20, ‘192.168.1.101’, 5432, 100, 1000),
(20, ‘192.168.1.102’, 5432, 100, 1000),
(20, ‘192.168.1.103’, 5432, 100, 1000);
ProxySQLAdmin> INSERT INTO mysql_users (username, password, default_hostgroup, active, max_connections) VALUES
(‘fgedu’, ‘fgedu123’, 10, 1, 5000);
ProxySQLAdmin> INSERT INTO mysql_query_rules (rule_id, active, match_pattern, destination_hostgroup, apply) VALUES
(1, 1, ‘^SELECT.*FOR UPDATE’, 10, 1),
(2, 1, ‘^SELECT’, 20, 1);
ProxySQLAdmin> LOAD MYSQL SERVERS TO RUNTIME;
ProxySQLAdmin> SAVE MYSQL SERVERS TO DISK;
ProxySQLAdmin> LOAD MYSQL USERS TO RUNTIME;
ProxySQLAdmin> SAVE MYSQL USERS TO DISK;
ProxySQLAdmin> LOAD MYSQL QUERY RULES TO RUNTIME;
ProxySQLAdmin> SAVE MYSQL QUERY RULES TO DISK;
## 3. 启动ProxySQL
$ systemctl start proxysql
$ systemctl enable proxysql
## 4. 应用连接配置
# 应用连接字符串
jdbc:postgresql://192.168.1.200:6033/fgedudb
## 5. 验证读写分离
# 查看ProxySQL状态
$ mysql -u admin -padmin -h 127.0.0.1 -P 6032 -e “SELECT * FROM mysql_servers;”
# 测试写操作
$ psql -h 192.168.1.200 -p 6033 -U fgedu -d fgedudb -c “INSERT INTO fgedu_test (name) VALUES (‘test’);”
# 测试读操作
$ psql -h 192.168.1.200 -p 6033 -U fgedu -d fgedudb -c “SELECT * FROM fgedu_test;”
# 查看备库状态
$ psql -h 192.168.1.101 -U fgedu -d fgedudb -c “SELECT * FROM fgedu_test;”
4.3 YashanDB基于应用层的读写分离
某企业在应用层实现YashanDB读写分离,提供更灵活的控制。
– 业务系统:内容管理系统
– 数据量:200GB
– 并发用户:2000
– 读请求比例:95%
– 写请求比例:5%
# 部署架构
– 主库:192.168.1.100
– 备库:192.168.1.101
# 应用层实现
## 1. Java应用实现
// 数据源配置
@Configuration
public class DataSourceConfig {
@Bean(name = “masterDataSource”)
@ConfigurationProperties(prefix = “spring.datasource.master”)
public DataSource masterDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = “slaveDataSource”)
@ConfigurationProperties(prefix = “spring.datasource.slave”)
public DataSource slaveDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = “routingDataSource”)
public DataSource routingDataSource(@Qualifier(“masterDataSource”) DataSource masterDataSource,
@Qualifier(“slaveDataSource”) DataSource slaveDataSource) {
Map
RoutingDataSource routingDataSource = new RoutingDataSource();
routingDataSource.setTargetDataSources(targetDataSources);
routingDataSource.setDefaultTargetDataSource(masterDataSource);
return routingDataSource;
}
@Bean
public PlatformTransactionManager transactionManager(@Qualifier(“routingDataSource”) DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
// 数据源路由
public class RoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSourceType();
}
}
// 数据源上下文
public class DataSourceContextHolder {
private static final ThreadLocal
public static void setDataSourceType(DataSourceType type) {
contextHolder.set(type);
}
public static DataSourceType getDataSourceType() {
return contextHolder.get() != null ? contextHolder.get() : DataSourceType.MASTER;
}
public static void clearDataSourceType() {
contextHolder.remove();
}
}
// 读写分离注解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
DataSourceType value() default DataSourceType.MASTER;
}
// 读写分离切面
@Aspect
@Component
public class DataSourceAspect {
@Before(“@annotation(dataSource)”)
public void before(JoinPoint point, DataSource dataSource) {
DataSourceType type = dataSource.value();
DataSourceContextHolder.setDataSourceType(type);
}
@After(“@annotation(dataSource)”)
public void after(JoinPoint point, DataSource dataSource) {
DataSourceContextHolder.clearDataSourceType();
}
}
// 服务层使用
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@DataSource(DataSourceType.MASTER)
public void createUser(User user) {
userMapper.insert(user);
}
@DataSource(DataSourceType.SLAVE)
public User getUserById(Long id) {
return userMapper.selectByPrimaryKey(id);
}
}
## 2. 验证读写分离
# 测试写操作
$ curl -X POST http://localhost:8080/api/users -H “Content-Type: application/json” -d ‘{“name”: “test”, “email”: “test@example.com”}’
# 测试读操作
$ curl http://localhost:8080/api/users/1
# 查看主库数据
$ psql -h 192.168.1.100 -U fgedu -d fgedudb -c “SELECT * FROM fgedu_user;”
# 查看备库数据
$ psql -h 192.168.1.101 -U fgedu -d fgedudb -c “SELECT * FROM fgedu_user;”
Part05-风哥经验总结与分享
5.1 YashanDB读写分离最佳实践
YashanDB读写分离的最佳实践:
- 选择合适的负载均衡器:根据业务需求和系统架构选择合适的负载均衡器,如PgBouncer、ProxySQL等
- 合理配置连接池:根据并发量和系统资源配置合适的连接池大小
- 监控复制延迟:定期监控备库的复制延迟,确保数据一致性
- 实现故障自动切换:当主库故障时,自动将写操作切换到备库
- 优化备库性能:为备库配置合适的参数,提高读性能
- 合理分配读请求:根据备库的性能和负载合理分配读请求
- 定期进行性能测试:定期测试读写分离的性能,优化配置
- 制定回滚方案:当读写分离出现问题时,能够快速回滚到单库模式
5.2 YashanDB读写分离常见问题
YashanDB读写分离的常见问题及解决方案:
## 1. 数据不一致
– 原因:备库复制延迟,导致读操作获取到旧数据
– 解决方案:
– 监控复制延迟,当延迟超过阈值时将读操作切换到主库
– 对数据一致性要求高的操作直接使用主库
– 调整复制参数,减少复制延迟
## 2. 负载均衡器成为性能瓶颈
– 原因:负载均衡器处理能力不足,无法处理大量请求
– 解决方案:
– 选择性能更好的负载均衡器
– 部署多个负载均衡器,实现负载均衡器的高可用
– 优化负载均衡器配置,提高处理能力
## 3. 应用连接失败
– 原因:负载均衡器配置错误,网络故障
– 解决方案:
– 检查负载均衡器配置
– 测试网络连接
– 配置应用连接池自动重连
## 4. 备库故障
– 原因:备库服务器故障,网络故障
– 解决方案:
– 实现备库的高可用
– 当备库故障时,自动将读操作切换到其他备库或主库
– 定期检查备库状态
## 5. 主库压力过大
– 原因:写操作过多,主库资源不足
– 解决方案:
– 优化写操作,减少事务大小
– 增加主库资源
– 考虑使用分片技术,分散写压力
5.3 YashanDB读写分离优化建议
YashanDB读写分离的优化建议:
## 1. 硬件优化
– 主库:配置高性能CPU和内存,使用SSD存储
– 备库:配置足够的内存和CPU,使用SSD存储
– 网络:使用高速网络,减少网络延迟
## 2. 软件优化
– YashanDB参数优化:调整shared_buffers、work_mem等参数
– 负载均衡器优化:调整连接池大小、超时时间等参数
– 应用优化:优化SQL语句,减少查询复杂度
## 3. 架构优化
– 增加备库数量:根据读请求量增加备库数量
– 实现多级缓存:使用Redis等缓存减少数据库读请求
– 数据分片:将数据分散到多个数据库实例
## 4. 监控优化
– 监控复制延迟:设置复制延迟告警
– 监控备库状态:及时发现备库故障
– 监控负载均衡器:监控负载均衡器的性能和状态
– 监控应用连接:监控应用连接数和连接池状态
## 5. 运维优化
– 定期维护:定期清理日志,优化表结构
– 定期备份:确保数据安全
– 定期演练:定期进行故障切换演练
– 文档化:记录读写分离的配置和维护流程
本文由风哥教程整理发布,仅用于学习测试使用,转载注明出处:http://www.fgedu.net.cn/10327.html
