达梦数据库两节点读写分离集群搭建详细过程(注意和主备守护集群的区别)


说明

读写分离集群的部署过程和达梦数据库两节点主备守护集群搭建详细过程非常接近,相似度90%以上。主要区别在于:

  1. 远程归档的方式不一致,详情见dmarch.ini文件配置
  2. 读写分离集群在客户端需要配置dm_svc.conf文件

一、背景介绍

DM 数据守护(Data Watch)是一种集成化的高可用、高性能数据库解决方案,是数据库异地容灾的首选方案。通过部署 DM 数据守护,可以在硬件故障(如磁盘损坏)、自然灾害(地震、火灾)等极端情况下,避免数据损坏、丢失,保障数据安全,并且可以快速恢复数据库服务,满足用户不间断提供数据库服务的要求。与常规的数据库备份(Backup)、还原(Restore)技术相比,数据守护可以更快地恢复数据库服务。随着数据规模不断增长,通过还原手段恢复数据,往往需要数个小时、甚至更长时间,而数据守护基本不受数据规模的影响,只需数秒时间就可以将备库切换为主库对外提供数据库服务。
本实验要求搭建两节点读写分离集群,并完成集群切换和恢复操作。

二、目的

完成2节点读写分离集群的搭建,要求如下:
(1)完成读写分离集群的部署,并测试建表和插入数据备机是否能及时同步,并可查询到数据。
(2)制造主机故障,测试备机可接管并持续提供服务。
(3)恢复故障主机,将故障主机加入集群。
(4)手动切换主备集群,恢复原主备集群的位置。
(5)测试读事务自动分发到备机的过程。

三、步骤

1. 集群规划

准备三台机器 DM1、DM2、DM_M,DM1 和 DM2 用来部署主备库,DM_M用来部署确认监视器。其中 DM1 和 DM2 配置两块网卡,一块接入内部网络交换模块,一块接入到外部交换机,DM_M接入内部网络。
三台机器都事先安装了 DM,安装路径为’/dm8’,执行程序保存在’/dm8/bin’目录中,数据存放路径为’/dm8/data’。
各主备库的实例名建议采用“组名_守护环境_序号”的方式命名,方便按组区分不同实例,注意总长度不能超过 16。本示例中组名为“G1”,配置为实时主备,主库命名为“G1_RT_01”,备库命名为“G1_RT_02”。

表1 服务器规划

机器名IP地址初始状态操作系统
DM11.1.1.1 192.168.75.130主库G1_RT_01CentOS Linux release 7.9.2009 (Core)
DM21.1.1.2 192.168.75.131备库G1_RT_02CentOS Linux release 7.9.2009 (Core)
DM_M1.1.1.3监视器CentOS Linux release 7.9.2009 (Core)

表2 端口规划

实例名PORT_NUMMAL_INST_DW_PORTMAL_HOSTMAL_PORTMAL_DW_PORT
DM1523052311.1.1.152325233
DM2523052311.1.1.252325233

2. 数据准备

分别在主库和备库上进行数据库初始化,并编辑dm.ini文件和dmarch.ini文件,开启归档
在这里插入图片描述
离线备份,数据库在dminit之后,还要启动一次以完成初始化动作,否则dmrman会报错“无法备份未初始化的数据库”
在这里插入图片描述
主库进行离线备份
在这里插入图片描述
从库进行离线恢复
在这里插入图片描述

3. 配置主库各ini文件

3.1 dm.ini文件

修改以下内容:

INSTANCE_NAME = G1_RT_01
PORT_NUM =5230  ##数据库实例监听端口
DW_INACTIVE_INTERVAL = 60 ##接收守护进程消息超时时间
ALTER_MODE_STATUS = 0 ##不允许手工方式修改实例模式/状态/OGUID
ENABLE_OFFLINE_TS = 2 ##不允许备库OFFLINE表空间
MAL_INI = 1 ##打开MAL系统
ARCH_INI = 1 ##打开归档配置
RLOG_SEND_APPLY_MON = 64 ##统计最近64次的日志发送信息

3.2 dmmal.ini文件

新建dmmal.ini文件,并配置以下内容:

#[dmdba@dm1 DAMENG]$ cat dmmal.ini
MAL_CHECK_INTERVAL = 5                          ##MAL链路检测时间间隔
MAL_CONN_FAIL_INTERVAL = 5                      ##判定MAL链路断开的时间
[MAL_INST1]
        MAL_INST_NAME = G1_RT_01                ##实例名,和dm.ini中的INSTANCE_NAME一致
        MAL_HOST = 1.1.1.1              ##MAL系统监听TCP连接的IP地址
        MAL_PORT = 5232                                 ##MAL系统监听TCP连接的端口
        MAL_INST_HOST = 192.168.75.130  ##实例的对外服务IP地址
        MAL_INST_PORT = 5230                    ##实例的对外服务端口,和dm.ini中的PORT_NUM一致
        MAL_DW_PORT = 5233                      ##实例本地的守护进程监听TCP连接的端口
        MAL_INST_DW_PORT = 5231                 ##实例监听守护进程TCP连接的端口
[MAL_INST2]
        MAL_INST_NAME = G1_RT_02
        MAL_HOST = 1.1.1.2
        MAL_PORT = 5232
        MAL_INST_HOST = 192.168.75.131
        MAL_INST_PORT = 5230
        MAL_DW_PORT = 5233
        MAL_INST_DW_PORT = 5231

3.3 dmarch.ini文件配置(注意和主备集群的区别)

新建dmarch.ini文件,并配置以下内容

#[dmdba@dm1 DAMENG]$ cat dmarch.ini
[ARCHIVE_TIMELY]
ARCH_TYPE=TIMELY
ARCH_DEST=G1_RT_02
[ARCHIEVE_LOCAL1]
ARCH_TYPE=LOCAL
ARCH_DEST=/dm8/data/DAMENG/arch
ARCH_FILE_SIZE=128
ARCH_SPACE_LIMIT=0

3.4 dmwatcher.ini文件配置

新建dmwatcher.ini文件,并配置以下内容

#[dmdba@dm1 DAMENG]$ cat dmwatcher.ini
[GRP1]
DW_TYPE = GLOBAL                                        ##全局守护类型
DW_MODE = AUTO                                          ##自动切换模式
DW_ERROR_TIME = 10                                      ##远程守护进程故障认定时间
INST_RECOVER_TIME = 60                          ##主库守护进程启动恢复的间隔时间
INST_ERROR_TIME = 10                            ##本地实例故障认定时间
INST_OGUID = 453331                             ##守护系统唯一OGUID值
INST_INI = /dm8/data/DAMENG/dm.ini      ##dm.ini配置文件路径
INST_AUTO_RESTART = 1                           ##打开实例的自动启动功能
INST_STARTUP_CMD = /dm8/bin/dmserver    ##命令行方式启动
RLOG_SEND_THRESHOLD = 0                         ##指定主库发送日志到备库的时间阈值,默认关闭
RLOG_APPLY_THRESHOLD = 0                        ##指定备库重演日志的时间阈值,默认关闭

4. 启动主库

主库启动要在前台mount形式,环境搭建完毕后,可关闭前台
在这里插入图片描述
修改主库OGUID
在这里插入图片描述
修改数据库模式
在这里插入图片描述

5. 配置从库各ini文件

5.1 修改dm.ini文件

找到并修改备库实例对应的dm.ini文件的以下内容:

INSTANCE_NAME = G1_RT_02
PORT_NUM =5230  ##数据库实例监听端口
DW_INACTIVE_INTERVAL = 60 ##接收守护进程消息超时时间
ALTER_MODE_STATUS = 0 ##不允许手工方式修改实例模式/状态/OGUID
ENABLE_OFFLINE_TS = 2 ##不允许备库OFFLINE表空间
MAL_INI = 1 ##打开MAL系统
ARCH_INI = 1 ##打开归档配置
RLOG_SEND_APPLY_MON = 64 ##统计最近64次的日志发送信息

5.2 dmmal.ini文件配置

和主库配置完全一致

#[dmdba@dm2 DAMENG]$ cat dmmal.ini
MAL_CHECK_INTERVAL = 5                          ##MAL链路检测时间间隔
MAL_CONN_FAIL_INTERVAL = 5                      ##判定MAL链路断开的时间
[MAL_INST1]
        MAL_INST_NAME = G1_RT_01                ##实例名,和dm.ini中的INSTANCE_NAME一致
        MAL_HOST = 1.1.1.1              ##MAL系统监听TCP连接的IP地址
        MAL_PORT = 5232                                 ##MAL系统监听TCP连接的端口
        MAL_INST_HOST = 192.168.75.130  ##实例的对外服务IP地址
        MAL_INST_PORT = 5230                    ##实例的对外服务端口,和dm.ini中的PORT_NUM一致
        MAL_DW_PORT = 5233                      ##实例本地的守护进程监听TCP连接的端口
        MAL_INST_DW_PORT = 5231                 ##实例监听守护进程TCP连接的端口
[MAL_INST2]
        MAL_INST_NAME = G1_RT_02
        MAL_HOST = 1.1.1.2
        MAL_PORT = 5232
        MAL_INST_HOST = 192.168.75.131
        MAL_INST_PORT = 5230
        MAL_DW_PORT = 5233
        MAL_INST_DW_PORT = 5231

5.3 dmarch.ini文件配置(注意和主备集群的区别)

#[dmdba@dm2 DAMENG]$ cat dmarch.ini
[ARCHIVE_TIMELY]
ARCH_TYPE=TIMELY
ARCH_DEST=G1_RT_01
[ARCHIEVE_LOCAL1]
ARCH_TYPE=LOCAL
ARCH_DEST=/dm8/data/DAMENG/arch
ARCH_FILE_SIZE=128
ARCH_SPACE_LIMIT=0

5.4 dmwatcher.ini配置

[dmdba@dm1 DAMENG]$ cat dmwatcher.ini
[GRP1]
DW_TYPE = GLOBAL                                        ##全局守护类型
DW_MODE = AUTO                                          ##自动切换模式
DW_ERROR_TIME = 10                                      ##远程守护进程故障认定时间
INST_RECOVER_TIME = 60                          ##主库守护进程启动恢复的间隔时间
INST_ERROR_TIME = 10                            ##本地实例故障认定时间
INST_OGUID = 453331                             ##守护系统唯一OGUID值
INST_INI = /dm8/data/DAMENG/dm.ini      ##dm.ini配置文件路径
INST_AUTO_RESTART = 1                           ##打开实例的自动启动功能
INST_STARTUP_CMD = /dm8/bin/dmserver    ##命令行方式启动
RLOG_APPLY_THRESHOLD = 0                        ##指定备库重演日志的时间阈值,默认关闭

6. 启动备库

启动备库失败,报错需要在dmrman中更新db_magic,原因是恢复数据库后,需要更新db_magic,详情见官方文档-备份恢复部分。
在这里插入图片描述
执行更新动作后备库恢复成功
在这里插入图片描述
备库启动成功
备库启动成功
修改数据OGUID和数据库模式为备库
在这里插入图片描述

7. 配置单实例监视器

创建dmmonitor.ini文件,配置以下内容:

[root@dm_m DAMENG]# cat dmmonitor.ini
MON_DW_CONFIRM = 1                      ##确认监视器模式
MON_LOG_PATH = /dm8/data/log ##监视器日志文件存放路径
MON_LOG_INTERVAL = 60           ##每隔60s定时记录系统信息到日志文件
MON_LOG_FILE_SIZE = 32          ##每个日志文件最大32M
MON_LOG_SPACE_LIMIT = 0         ##不限定日志文件总占用空间
[GRP1]
MON_INST_OGUID = 453331 ##组GRP1的唯一OGUID值
MON_DW_IP = 1.1.1.1:5233
MON_DW_IP = 1.1.1.2:5233
MON_DW_IP = 1.1.1.3:5233

8. 启动进程

启动主备库的守护进程
在这里插入图片描述
在这里插入图片描述
启动监视器进程
在这里插入图片描述

9. 主备集群数据插入及查询测试

在主库上建表并测试数据插入后提交,在备库上可以查询到对应数据;
在这里插入图片描述
在这里插入图片描述
但是在备库上无法执行创建表动作
在这里插入图片描述

10. 故障模拟测试

10.1 关闭主库数据库进程

主库为前台运行,关闭前台进程,查看现象
在这里插入图片描述
监控进程显示主库短暂shutdown后自动拉起
在这里插入图片描述

10.2 关闭备库前台数据库进程

在这里插入图片描述
监控程序经过短暂shutdown后自动拉起
在这里插入图片描述

10.3 关闭主库守护进程

监控器处主库的守护WSTATUS显示异常。主库数据库进程运行正常
在这里插入图片描述
在这里插入图片描述

10.4 关闭主库守护进程,同时Kill掉主库进程

在这里插入图片描述
Monitor显示主库异常,备库自动切换
在这里插入图片描述
备库自动接管主库业务,状态切换为primary,可以执行数据写入操作
在这里插入图片描述
在这里插入图片描述

11. 故障恢复测试

依次启动故障库的数据库进程和守护进程,监控器显示该节点自动被设置为standby节点
在这里插入图片描述
在这里插入图片描述

12. 读写分离测试

配置客户端本地的dm_svc.conf文件,退出客户端,重新创建连接。配置如下:
注意:DMRW1和DMRW2配置不一样,对比验证读写分离的效果。

TIME_ZONE=(480)
LANGUAGE=(cn)
DMRW1=(192.168.75.130:5230,192.168.75.131:5230)
DMRW2=(192.168.75.130:5230,192.168.75.131:5230)
##服务配置
[DMRW1]
RW_SEPARATE=(1)
RW_PERCENT=(0)
[DMRW2]
RW_SEPARATE=(1)
RW_PERCENT=(100)

在这里插入图片描述
DMRW1测试:由于开启读写分离,且主库读取比例设置为0,所以读取操作必定分配到备库
在这里插入图片描述
在这里插入图片描述
DMRW2测试:由于开启读写分离,且主库读取比例设置为100,所以读取操作必定分配到主库
在这里插入图片描述
在这里插入图片描述

四、实验结论

1.读写分离集群至少需要两个数据库节点和一个监控节点,且网络需要切分为心跳网络和业务网络,监控节点位于心跳网络;
2.读写分离集群可以实现主备数据库的无缝切换,且在故障库恢复之后,开启服务可自动作为备节点加入集群。
3.可以通过客户端测的配置文件dm_svc.conf文件来配置是否开启读写分离,并设置主库的读取比例。

五、实验心得

1. Windows端dm_svc.conf文件如何生效

修改并保存dm_svc.conf文件之后,断开后重新连接并不会使配置生效,必须重启manager

社区地址:https://eco.dameng.com

  • 14
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现Spring Boot与达梦数据库读写分离集群,您需要进行以下步骤: 1. 配置数据源:打开Spring Boot项目的application.properties文件,配置主库和从库的数据源信息。例如: ``` # 主库数据源 spring.datasource.primary.url=jdbc:dme://localhost:5236/demo spring.datasource.primary.username=root spring.datasource.primary.password=root # 从库数据源 spring.datasource.secondary.url=jdbc:dme://localhost:5236/demo spring.datasource.secondary.username=root spring.datasource.secondary.password=root ``` 2. 配置数据源路由:使用Spring Boot提供的AbstractRoutingDataSource类,创建一个数据源路由器,根据SQL语句的类型(读/写)选择合适的数据源。例如: ``` public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { // 根据上下文选择合适的数据源 return DatabaseContextHolder.getDatabaseType(); } } ``` 3. 配置数据源上下文:使用ThreadLocal类保存当前线程的数据源类型,以便在数据源路由器中选择正确的数据源。例如: ``` public class DatabaseContextHolder { private static final ThreadLocal<DatabaseType> contextHolder = new ThreadLocal<>(); public static void setDatabaseType(DatabaseType databaseType) { contextHolder.set(databaseType); } public static DatabaseType getDatabaseType() { return contextHolder.get(); } public static void clearDatabaseType() { contextHolder.remove(); } } public enum DatabaseType { PRIMARY, SECONDARY } ``` 4. 配置事务管理器:使用Spring Boot提供的JpaTransactionManager类,为主库和从库分别配置事务管理器。例如: ``` @Configuration @EnableTransactionManagement public class TransactionConfig { @Autowired @Qualifier("primaryEntityManagerFactory") private EntityManagerFactory primaryEntityManagerFactory; @Autowired @Qualifier("secondaryEntityManagerFactory") private EntityManagerFactory secondaryEntityManagerFactory; @Bean(name = "primaryTransactionManager") public PlatformTransactionManager primaryTransactionManager() { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(primaryEntityManagerFactory); return transactionManager; } @Bean(name = "secondaryTransactionManager") public PlatformTransactionManager secondaryTransactionManager() { JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory(secondaryEntityManagerFactory); return transactionManager; } } ``` 5. 配置JPA和Hibernate:为主库和从库分别配置JPA和Hibernate。例如: ``` @Configuration @EnableJpaRepositories( basePackages = "com.example.demo.primary", entityManagerFactoryRef = "primaryEntityManagerFactory", transactionManagerRef = "primaryTransactionManager" ) @EnableTransactionManagement public class PrimaryDataSourceConfig { @Primary @Bean(name = "primaryDataSource") @ConfigurationProperties(prefix = "spring.datasource.primary") public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } @Primary @Bean(name = "primaryEntityManagerFactory") public LocalContainerEntityManagerFactoryBean primaryEntityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("primaryDataSource") DataSource dataSource) { return builder .dataSource(dataSource) .packages("com.example.demo.primary") .persistenceUnit("primary") .build(); } @Primary @Bean(name = "primaryJpaProperties") @ConfigurationProperties(prefix = "spring.jpa.primary") public JpaProperties primaryJpaProperties() { return new JpaProperties(); } @Primary @Bean(name = "primaryHibernateProperties") @ConfigurationProperties(prefix = "spring.jpa.primary.hibernate") public HibernateProperties primaryHibernateProperties() { return new HibernateProperties(); } } @Configuration @EnableJpaRepositories( basePackages = "com.example.demo.secondary", entityManagerFactoryRef = "secondaryEntityManagerFactory", transactionManagerRef = "secondaryTransactionManager" ) @EnableTransactionManagement public class SecondaryDataSourceConfig { @Bean(name = "secondaryDataSource") @ConfigurationProperties(prefix = "spring.datasource.secondary") public DataSource secondaryDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "secondaryEntityManagerFactory") public LocalContainerEntityManagerFactoryBean secondaryEntityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("secondaryDataSource") DataSource dataSource) { return builder .dataSource(dataSource) .packages("com.example.demo.secondary") .persistenceUnit("secondary") .build(); } @Bean(name = "secondaryJpaProperties") @ConfigurationProperties(prefix = "spring.jpa.secondary") public JpaProperties secondaryJpaProperties() { return new JpaProperties(); } @Bean(name = "secondaryHibernateProperties") @ConfigurationProperties(prefix = "spring.jpa.secondary.hibernate") public HibernateProperties secondaryHibernateProperties() { return new HibernateProperties(); } } ``` 6. 使用数据源:在需要使用数据源的地方,通过调用DatabaseContextHolder.setDatabaseType()方法设置当前线程的数据源类型,然后执行SQL语句即可。例如: ``` @Service public class UserService { @Autowired private UserRepository userRepository; @Transactional public void save(User user) { DatabaseContextHolder.setDatabaseType(DatabaseType.PRIMARY); userRepository.save(user); DatabaseContextHolder.setDatabaseType(DatabaseType.SECONDARY); userRepository.save(user); } } ``` 这样,就可以实现Spring Boot与达梦数据库读写分离集群了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值