【摘要】openGauss数据库作为开源数据库的后起之秀,这两年蓬勃发展,关于其细致的安装教程,网上并不缺少,但其作为新的数据库,如何做好企业及部署,这是值得探讨的方向。本文结合商业数据库应用和部署的经验,讨论openGauss数据库企业级应用需求下需要考虑的方方面面,具有独到的参考价值。
openGauss数据库作为开源数据库的后起之秀,这两年开源社区蓬勃发展,越来越多的公司和企业加入到openGauss开源社区。作为纯国产开源的关系型数据库,当前部分银行已经尝试在生产应用openGauss数据库,同时也有很多合作伙伴在openGauss内核的基础上推出各自的商业版本。
openGauss数据库至今为止基本保持三月一次发版的节奏。每次发版都会发现内容非常多,不仅包含大功能的新增和改进,同时也有非常多的问题被修复。可以说openGauss开源社区的投入,并不逊色于传统的大型商业数据库公司。国内几家合作伙伴的加入和贡献,也让openGauss数据库生态越来越好,这也给企业在生产使用openGauss数据库带来更大的信心。
作为新的数据库,如何做好企业级部署,这是值得探讨的地方。这篇文章并不是一个细致的安装教程,网上也不缺乏该类教程,而是结合商业数据库应用和部署的经验,讨论下openGauss数据库企业级应用需求下需要考虑的方方面面。
openGauss作为集中式的单机数据库,这里的架构设计主要是讨论高可用怎么做,同城和异地容灾怎么做。
传统的数据库本地高可用有两种比较流行的方式:集中式存储方式和数据库复制方式。Db2和Oracle等商业数据库的部署大部分都是采用集中式存储的模式。而MySQL数据库就基本都是通过数据库复制的模式来实现高可用。
集中式存储方案是目前企业级部署中应用最广泛也是最成熟的方案。数据库的数据部署在存储上,上层通过系统的HA工具监控和切换。然而这种方式也有缺点。首先是外置存储的性能和内置SSD盘的性能差异在数据库应用场景对比还是比较明显的。其次是磁盘数据的损坏需要通过数据库恢复来修复,相对恢复时间较长。最后从部署成本来说,集中式存储方案部署较重,需要存储布线等。
数据库复制方案是通过数据库日志的物理或者逻辑同步,在备机实时重做主机的修改,从而保证主备数据库的数据一致性。这也是一个非常成熟的方案。Db2和Oracle等商业数据库都有基于数据库日志物理同步的功能。MySQL的日志逻辑复制也应用非常广泛。这种方案下数据库主机上的存储采用内置盘,主备的数据是完全隔离的,更好的利用了内置盘的性能和做到了存储上的隔离。
openGauss数据库也支持数据库日志的物理复制和逻辑复制。逻辑复制存在一个比较重大的缺点,就是对于大事务的数据回放性能不好。因此在openGauss数据库的高可用设计中,数据库日志物理同步是当前最好的方案。
官方的架构图也是推荐使用这种方式。openGauss数据库提供了om工具来帮助部署和管理openGauss数据库的主备集群节点。openGauss数据库的物理复制支持一主多备和级联备等功能,未来也会加入延时复制功能。openGauss的备机是支持只读操作的,可以实现读写分离,减少主库的读负载。
建议本地高可用就通过数据库物理同步来实现。建议打开备机可读,设置wal_level为hot_standby。为了保障数据一致性,synchronous_commit建议修改为remote_write或者remote_receive。如果只有一主一从的情况下,建议设置most_available_sync为on。最后通过第三方的高可用集群软件来监视openGauss的主从状态,实现故障自动切换等高可用场景。
openGauss数据库主从架构下,客户端如何连接到主数据库呢?又怎么做读写分离?这个时候就需要讨论下客户端连接数据库的几种方式:VIP,DNS和主机列表。因为openGauss数据库的jdbc驱动里支持设置多个主机,并提供参数设置只连主节点还是只连备节点,这也应对了读写分离的需求。
传统的VIP模式只能支持应用连接到主节点上,从节点的读请求是不太好设置的。增加读VIP的管理对于高可用软件来说就太复杂了。VIP管理还有一个限制是必须属于同一网段。对于同城双中心不能采用相同网段的情况下,VIP漂移就不能实现。
DNS也具备高可用性,但是只能检测到机器IP是否存在,不能检测openGauss的服务,所以采用DNS的高可用相对来说不太适合数据库来使用。
例如下面这个例子就是只连主库的客户端设置:
url=jdbc:postgresql://:26000,:26000/?connectTimeout=5&targetServerType=master&tcpKeepAlive=true
我比较偏向于采用主机列表的方式,通过配置客户端参数,实现自动主库发现,负载均衡,只读从库等各类应用场景需求。这种方式也避免了VIP,DNS在不同架构下的管理复杂性,相对更通用一些。缺点是增加了一点客户端数据源配置的复杂性。
数据库级的同城容灾可能会分成不同的级别来实现。金融行业的同城数据中心一般都要求具备全量承载数据和业务的能力。数据库实现同城容灾最主要目标是最小化RPO和RTO指标,在此基础上可能还会有同城灾备数据库的只读访问等需求。同城容灾的实现方式也有两种主流模式:存储复制和数据库复制。优缺点和本地高可用差不多。但是如果本地openGauss采用了内置盘部署,那么也就不支持做存储复制的容灾模式了。所以建议openGauss数据库还是采用数据库复制的方式。注意在设置synchronous_standby_names的时候要保证同城至少有一个节点处于数据同步状态。
这里稍微讨论下同城容灾的几个定位:
1.同城是否需要保障RPO=0?
金融行业的大部分需要做同城容灾的应用都要求RPO=0,不能容忍同城切换丢失数据。因此在设计synchronous_standby_names的时候需要加上同城备机并设置成同步模式。然而双中心间的网络稳定性显然要比同中心要差很多,为了避免设置了强同步后,双中心网络抖动可能会影响主机性能,可以考虑设置most_available_sync参数为ON,丢失备机的情况下主机可以断开备机并恢复工作。
2.同城数据库是否需要只读访问?
数据库的备机提供只读访问的能力,包括同城的数据库备机。那么是否真的需要去启用这个功能呢?从前端业务的性能考虑,显然同机房访问要比跨机房访问要更快一些。而从后端数据库的处理能力来说,需要只读能力扩展的需求,都是为了满足减轻主库的运行压力,并且还要求应用能够配置单独的只读数据源,从应用层就解决好读写分离。在这些场景需求里,显然本地的备机只读访问就可以解决这些问题,所以大概率是不需要升级到同城只读访问的性能扩展需求的。只有一种情况下需要同城只读访问,那就是为了架构的便利性,同城切换的便利性等需求。这种情况下并不是以扩展性能为目的,而是以技术架构方案的整体性设计需要。
3.同城是否需要自动切换?
这个问题一直是讨论的比较多的地方。保守一点的想法是同城切换都是交给人工来决策的。激进一点的想法是同城都保障不丢数据库,当然也可以自动切换,交给HA监控并自动化切换修复多好。所以面对不同的选择,这里对于同城的定位就不一样,所涉及的HA架构设计也很不相同。个人认为除非同城双中心定位完全无主次之分,否则大部分应用还是偏向于运行在主机房,这种情况下,同城切换适合交给人为决策,自动化平台快速实现。
异地容灾也需要分不同的数据保护类型。可能最关键的应用也就是尽可能减少RPO和RTO。这种类型的关键应用也是建议通过数据库主从复制的方式来实现,只是异地的数据库节点通常都是设置为异步模式。
openGauss数据库支持级联备,也就是从一主多从的某个从库上,配置一个级联备机,指向异地容灾的数据库从库。这也是比较推荐的方式,减少主库的压力。
这里主要讨论下安装部署里的操作系统用户,数据库用户等规划设计。
操作系统用户主要是安装openGauss的用户和组,以及需要使用gsql客户端访问openGauss数据库的操作系统用户。例如华为的openGauss数据库默认采用omm用户和dbgrp用户组,这在华为的高斯分布式产品里都是这个设计的。我们使用openGauss的时候也延续了这个习惯。
omm操作系统用户具有openGauss数据库程序的访问权限,能执行gsql、gs_ctl等工具。而这些工具的权限一般是700,也就是说只有omm用户能使用。而通常omm用户访问本地的openGauss是通过socket,可以使用超级用户,还可以免密,因此这个用户完全是交给系统管理员的,不适合交给用户使用。
那么如果应用用户需要使用gsql等工具怎么办?这种情况下建议设计一个系统用户appuser,并为它安装一个单独的gsql等工具客户端,通过IO连接数据库。
数据库用户也应该分为几种类型:超级管理员、监控管理员、数据库管理员和普通数据库用户。
一开始initdb的初始用户就是超级管理员用户,具有sysadmin的权限。这个用户通常不会交给应用来使用,甚至不应该当做超级管理员来使用。这个用户只能是作为能够登录到这个操作系统上应急的免密超级用户。
所以为了管理openGauss数据库,我们还需要创建一个单独的管理员用户具备sysadmin角色权限。例如设计一个gsadmin用户,在运维工具平台通过这个用户远程管理所有的openGauss数据库。
create user gsadmin with sysadmin password 'xxxxxxxx'
还有一种用户是远程备份用户,建议创建单独的用户并sysadmin角色权限。
openGauss数据库从2.0.0版本开始提供了monadmin角色。这个角色权限能够访问所有的系统视图。因此对于监控用户,建议配置这个角色即可。
create user monadmin with monadmin password 'xxxxxxxx'
openGauss的数据库是相互隔离的。对于每一个独立的数据库,可以设置一个数据库管理员角色的用户,给予全库的管理权限。
grant all privileges on database <dbname> to <username>
这种用户通常也是作为应用来连接的用户,具备全库的对象管理能力,也具备数据修改查询能力。这是一种很常见的用法, 很少有在应用数据源配置连接用户的时候还继续做细致的权限分离。当然数据库权限管理是具备相关能力的。
除了本应用系统使用的数据库管理员用户,可能还存在类似跨系统访问的特殊需求情况。例如抽取数据的用户,只读访问的用户等。这些用户建议创建单独的最小授权用户。
在openGauss数据库的目录下,设计了pg_hba.conf配置文件,用来定义用户访问数据库的方式,也可以称作是白名单管理。定义了在什么访问类型下,访问哪个数据库,是哪个用户,从哪里来访问,采用何种验证方式。这些组合可以实现很复杂的白名单过滤规则。这种可以过滤IP的用户访问控制有点像mysql,但是又完全不一样。openGauss里的数据库用户名对应的就是一个用户角色,不像mysql,如果用户名里的IP不一样,其实算是不同的用户。
不过从金融行业的实践来看,数据库服务器和应用服务器等在隔离的网络区内,主机间的访问控制通过网络来管理,基本不需要底层数据库来实现复杂的管控。为了管理方便,不如全部放开数据库级别的ip管控。下面这个例子使用gs_guc工具配置整个集群所有的白名单:
gs_guc reload -N all -I all -h "host all all 0.0.0.0/0 sha256"
翻译过来就是任何IP基于host请求过来的所有用户访问所有数据库都采用sha256加密算法验证用户。
openGauss数据库建议配置至少两个独立的文件系统。一个用来放数据库,一个用来放数据库运行中产生的归档日志,诊断日志等。
数据库存放的路径建议放在单独的文件系统上。部分重要的业务系统也建议将在线日志pg_xlog放在单独的文件系统上,与数据data分开。然而从实际情况来看,data和xlog采用不同的文件系统,除非底层的盘也是独立的,性能是没有什么区别的。因此暂时建议采用一个就可以了。
数据库运行中产生的诊断日志,审计日志,归档日志,core文件等,都是不影响数据库运行的,但是又持续不断的产生的。因此需要单独规划一个文件系统来存放,同时做好这些日志的清理策略。这个文件系统也可以用来规划存放脚本文件,备份文件,跑批文件等临时文件。
例如将归档日志路径、审计日志路径、core文件路径和诊断日志路径都设置到这个文件系统下面。
gs_guc set -c "archive_command = 'cp %p /gausslog/archive/%f'"
gs_guc set -c "audit_directory='/gausslog/log/omm/pg_audit'"
gs_guc set -c "bbox_dump_path='/gausslog/corefile'"
gs_guc set -c "log_directory='/gausslog/log/omm/pg_log'"
规划好了数据库安装,下一步是设计相关运维需求方案。
安装完成之后最先需要的是根据业务负载需求设置相关参数。这些参数细节比较多,需要好好阅读相关资料再做选择。其中max_process_memory和shared_buffers是比较关键的内存参数,建议按照操作系统内存总量(数据库独占资源)的70%和50%来设置。
增量检查点和双写开关应该打开。这个是openGauss相对于postgresql比较大的改进机制,解决了全量检查点的性能瓶颈问题。enable_opfusion开关也建议打开,对于高并发小事务的竞争会有改善。
gs_guc set -c "cstore_buffers = 128MB"
gs_guc set -c "enable_alarm = off"
gs_guc set -c "enable_delta_store = on"
gs_guc set -c "enable_double_write = on"
gs_guc set -c "enable_incremental_checkpoint = on"
gs_guc set -c "enable_wdr_snapshot = off"
gs_guc set -c "enable_xlog_prune = on"
gs_guc set -c "log_min_duration_statement = 1s"
gs_guc set -c "maintenance_work_mem=1GB"
gs_guc set -c "max_connections = 2000"
gs_guc set -c "max_files_per_process = 10000"
gs_guc set -c "max_prepared_transactions = 2000"
gs_guc set -c "session_timeout = 0"
gs_guc set -c "shared_buffers = 2GB"
gs_guc set -c "temp_buffers = 128MB"
gs_guc set -c "update_lockwait_timeout = 1min"
gs_guc set -c "wal_buffers = 64MB"
gs_guc set -c "wdr_snapshot_interval = 10min"
gs_guc set -c "work_mem = 512MB"
gs_guc set -c "log_temp_files = 100MB"
gs_guc set -c "enable_mergejoin = ON"
gs_guc set -c "enable_nestloop = ON"
gs_guc set -c "advance_xlog_file_num = 10"
gs_guc set -c "pagewriter_sleep = 1000ms"
gs_guc set -c "xloginsert_locks = 50"
gs_guc set -c "lockwait_timeout = 1min"
gs_guc set -c "enable_opfusion = off"
gs_guc set -c "max_process_memory=3GB"
为了降低DBA的运维工作量,使用openGauss的过程里要充分利用好数据库的自动管理机制。尤其是跟性能动态调整相关的机制。
openGauss数据库内部的执行计划有两种选择方式,基于规则和基于代价。基于代价的这种方式依赖于数据库的统计信息。数据库的统计信息是由analyze命令采集的。除了人为发出analyze命令,openGauss内部也提供了自动analyze的功能。建议打开autoanalyze和autovacuum的开关。
openGauss的存储引擎还有一个比较特殊的地方,就是update和delete都会保留原元组,作为MVCC的基石。这种机制会不停产生死元组,并且一直占据表内的空间。这种情况下需要vacuum命令来回收这些空间,后续的数据才能使用。openGauss提供了autovacuum机制,能够根据表的数据变化量自动触发vacuum机制,回收死元组。但是在vacuum受到MVCC机制影响,清理数据会检查数据库里最老的事务。因此除了打开autovacuum,还需要控制好数据库内的最长事务。所以需要监控pg_stat_activity中xact_start不为空的事务,判断长事务。如果遇到一直处于idle in transaction状态的连接,一定要检查处理。
openGauss数据库提供了安全审计功能,可以设置相关审计参数,将审计日志记录下来,通过sql函数pg_query_audit查看审计记录。
下表展示了审计相关的配置项。其中DML操作和SELECT操作审计功能建议关闭,因为审计量太大了。
如果需要针对特殊用户进行SQL级别的审计,可以使用AUDIT POLICY统一审计方式。打开enable_security_policy开关统一审计策略才可以生效。
统一审计默认输出节点的rsyslog日志中,在操作系统后台服务配置文件/etc/rsyslog.conf中添加代码:
local0.* /var/log/localmessages
执行如下命令:
sudo touch /var/log/localmessages
sudo chmod 600 localmessages
sudo systemctl restart rsyslog
然后通过创建 AUDIT POLICY实现。
CREATE AUDIT POLICY [ IF NOT EXISTS ] policy_name { { privilege_audit_clause | access_audit_clause } [ filter_group_clause ] [ ENABLE | DISABLE ] };
例如仅审计user1用户的iud操作:
CREATE AUDIT POLICY adt1 ACCESS INSERT,UPDATE,DELETE FILTER ON ROLES(user1);
对于企业级的数据库部署运维,监控告警和应急处理是最重要的。对于openGauss的监控告警需要达到的目标是能够准确发现问题并告警,能够快速基于监控数据分析根因并处理。为了实现这个目标,建议openGauss数据库的监控一方面要全面采集性能和状态指标,另一方面对于关键指标实现准确告警。
openGauss提供了很多监控视图。特别是dbe_perf模式下的监控视图,内容包括OS、Instance、Memory、File、Object、Workload、Session/Thread、Transaction、Query、Cache/IO、Utility、Lock、Wait Events、Configuration、Operator和Workload Manager等对象的监控。这些监控视图也是WDR报告的快照来源。建议统一采集这些性能快照视图数据,通过智能运维管理和分析。
相对于监控数据采集的全面性,告警指标需要挑选全局有意义的对象。重要的告警有监控数据库状态、主从复制状态、在线会话数量、等待会话数量、长事务、长SQL、死锁、回滚语句数量等。
openGauss数据库支持的备份方式还是比较全面的。而企业级的数据库在这方面要求也很高。一方面为了出问题尽快恢复,数据库定期备份策略都比较激进,另一方面备份过程还要尽量减少性能影响和资源占用。例如银行一般每天都会备份全量数据库,时刻备份归档日志,为了减少性能影响,备份会选择从库执行。如果是远程备份,那么还会采用单独的备份网段,与生产业务网隔离。
很多国内备份厂家当前也一直在测试备份openGauss数据库,相信很快就会有类似于NBU这样的备份产品出现,并在企业级应用。openGauss数据库支持远程备份,当前也可以建立基于网络的备份服务器,通过备份专用网,统一调度管理所有数据库的备份。
其实做好openGauss企业级部署,就是拿之前对于Db2和Oracle的运维标准来建设openGauss数据库的运维体系。openGauss数据库技术特点与这些商业数据库相比差别不大,当前欠缺的也只是生态和产品成熟性。相信这两方面会越来越好,因此我对于openGauss数据库在企业中的应用前景非常看好,也希望其尽快成为一个合格的国产替代品。