转载自 pg_auto_failover简介:高可用性和自动故障转移Postgres扩展
在设计pg_auto_failover时,我们的目标是:为Postgres提供易于设置的业务连续性解决方案,该解决方案实现系统中任何一个节点的容错能力。
重要的是要了解pg_auto_failover已针对业务连续性进行了优化。万一丢失单个节点,由于PostgreSQL同步复制,pg_auto_failover能够继续PostgreSQL服务,并在这样做时防止任何数据丢失。
pg_auto_failover简介
用于Postgres的pg_auto_failover解决方案旨在提供一种易于设置且可靠的自动化故障转移解决方案。该解决方案包括由软件驱动的决策,以决定何时在生产中实施故障转移。
任何自动故障转移系统中最重要的部分是决策策略,我们在线上有完整的文档章节,内容涉及pg_auto_failover故障容忍机制。
使用pg_auto_failover时,将部署多个活动代理来跟踪您的生产Postgres安装属性:
1) 监视器是一个本身具有pg_auto_failover扩展名的Postgres数据库,它注册并检查活动Postgres节点的运行状况。
2) 在pg_auto_failover监视器中注册的每个Postgres节点也必须运行本地代理pg_autoctl运行服务。
3) 每个受管理的Postgres服务在同一个组中有两个设置在一起的Postgres节点。一个监视器可以根据需要设置多个Postgres管理组。
通过这样的部署,监控器会定期连接到每个已注册的节点(默认为20秒),并在其pgautofailover.node表中注册成功或失败。
此外,每个Postgres节点上的pg_autoctl运行服务还会检查Postgres是否正在运行,并监视其他节点的pgstat replication统计信息。此Postgres系统视图使我们的本地代理能够发现主节点和备用节点之间的网络连接。本地代理定期每隔5s向监视器报告每个节点的状态,除非需要进行转换,然后立即进行。
pg_auto_failover监视器根据集群中两个节点的已知状态做出决策,并且仅遵循我们精心设计以确保节点收敛的有限状态机。特别是,只有在pg_autoctl代理报告成功实现了确定的过渡到新状态后,FSM才取得进展。关于故障转移逻辑的体系结构文档部分包含FSM的映像,我们使用这些映像来确保pgautofailover中的自动故障转移决策。
pg_auto_failover快速入门
首次尝试该项目时,最简单的方法是创建一个监视器,然后注册一个主要的Postgres实例,然后注册一个辅助的Postgres实例。
运行以下命令来创建监视器,包括使用initdb初始化Postgres集群,安装我们的pg_auto_failover扩展以及在HBA文件中打开连接特权。
$ mkdir /tmp/pg_auto_failover/test
$ export PGDATA=/tmp/pg_auto_failover/test/monitor
在本地端口6000的本地主机上创建Monitor Postgres实例:
$ pg_autoctl create monitor --nodename localhost --pgport 6000
查看监视器:
$ pg_autoctl show uri
postgres://autoctl_node@localhost:6000/pg_auto_failover
在另一个终端中,创建一个主要的PostgreSQL实例:
$ export PGDATA=/tmp/pg_auto_failover/test/node_a
$ pg_autoctl create postgres --nodename localhost --pgport 6001 --dbname test --monitor postgres://autoctl_node@localhost:6000/pg_auto_failover
此命令将PostgreSQL实例注册到监视器,使用pg_ctl initdb创建实例,为监视器运行状况检查准备一些连接权限,并创建一个名为test的数据库。 然后,执行由监视器排序的第一个转换,从状态INIT到达状态SINGLE。
测试时以交互方式启动pg_autoctl运行服务。 对于生产设置,这将进入需要引导时间的系统服务,例如systemd。
$ pg_autoctl run
最后一行将每5s重复一次,这表明主节点运行状况良好,并且可以正常连接到监视器。 而且,它现在处于SINGLE状态,一旦新的Postgres节点加入该组,它就会改变。
在另一个终端上创建辅助Postgres实例:
$ export PGDATA=/tmp/pg_auto_failover/test/node_b
$ pg_autoctl create postgres --nodename localhost --pgport 6002 --dbname test --monitor postgres://autoctl_node@localhost:6000/pg_auto_failover
这次向监视器的注册返回WAITSTANDBY状态,该状态驱动pgautoctl创建辅助节点。 这是因为服务器已存在于组中,并且当前为SINGLE。 同时,监视器将目标状态WAIT_PRIMARY分配给主节点,local pgautoctl agent从监视器数据库和openpghba.conf中检索新节点的节点名称和端口以进行复制。 完成后,辅助节点继续pg_basebackup,安装arecovery.conf`文件,启动本地Postgres服务,并通知监视器有关达到目标状态的信息。
不过,我们仍在CATCHING_UP。 这意味着尚无法进行自动故障转移。 为了能够安排故障转移,我们需要在新节点上运行本地服务,监视Postgres的运行状况和复制状态,并每5秒向监视器报告一次:
$ pg_autoctl run
现在,新节点处于SECONDARY状态,并继续向监视器报告,准备在监视器做出决定时提升本地Postgres实例。
pg_auto_failover自动和手动故障转移
每个节点使用pg_auto_failover来配置具有自动故障转移功能的PostgreSQL集群所需要做的是:1) 用pg_autoctl create ...创建节点,2) 运行pg_autoctl来运行本地服务,以实现由监视器决定的转换。
要见证故障转移,最简单的方法是停止pg_autoctl运行服务(在运行它的终端中使用^ C或在其他任何地方使用pg_autoctl stop --pgdata ...;然后也使用pg_ctl停止Postgres实例- D ...停下来)。
当仅停止Postgres时,pg_autoctl运行服务将检测到该情况为异常,然后首先尝试重新启动Postgres。当使用默认pg_auto_failover参数连续3次未能启动Postgres时,才认为故障转移是适当的。
注入故障转移条件的另一种方法是礼貌地要求监视器为您安排一个:
$ psql postgres://autoctl_node@localhost:6000/pg_auto_failover
> select pgautofailover.perform_failover();
应用程序和客户端的连接字符串
整个设置以pg_auto_failover条款的形式运行。 默认格式名为default,并且包含两个Postgres实例的单个组。 想法是只有一个入口,可以将应用程序连接到任何给定的形式。 要获取到我们的pg_auto_failover托管的Postgres服务的连接字符串,请发出以下命令,例如 在监视器终端上:
$ pg_autoctl show uri --formation default
postgres://localhost:6002,localhost:6001/test?target_session_attrs=read-write
在这里使用libpq的多主机功能,基于libpq (大多数都是这样)时,可以与任何现代Postgres驱动程序一起使用,并且已知其他本地驱动程序也可以实现相同的功能,例如JDBC Postgres驱动程序。
$ psql postgres://localhost:6002,localhost:6001/test?target_session_attrs=read-write
psql (12devel, server 10.7)
Type "help" for help.
test# select pg_is_in_recovery();
pg_is_in_recovery
═══════════════════
f
(1 row)
当使用这样的连接字符串时,连接驱动程序将连接到第一台主机并检查是否接受写操作,如果不是,则连接到第二台主机并再次检查。那是因为我们希望targetsessionattrs是可读写的。
使用Postgres此核心功能,实现了客户端的高可用性:在发生故障转移的情况下,我们的node_b将成为主要对象,并且我们需要应用程序现在将node_b定位为写入对象,并且该操作将在连接驱动程序中自动完成。
高可用性,容错和业务连续性
因此pgautofailover就是关于业务连续性的,并且为每个主要的Postgres服务器使用一个备用服务器。
在用于Postgres的经典HA设置中,我们依靠每个主服务器都有两个备用服务器的同步复制。当您想要实现零或接近零的RTO和RPO目标时,这就是预期的架构。
同样,每个主节点使用两个备用节点的想法是,您会丢失任何备用服务器,并且仍然知道在两个不同的地方仍可以使用数据。
在某些情况下,最佳的生产设置折衷方法与当前Postgres HA工具支持的方法有所不同。有时可以在需要执行灾难恢复过程时面对服务中断,因为对这种情况下必要风险的评估符合生产预算,预期的SLA或其组合。
并非所有项目都需要超过99.95%的可用性,即使没有走到最后一英里,有时也需要达到99.999%的目标。此外,尽管物联网和其他一些用例(例如庞大的用户群)需要HA解决方案,这些解决方案需要将TB级数据扩展到PB级数据,但许多项目却是针对较小的受众和数据集的。当您拥有千兆字节的数据,甚至数十千兆字节的数据时,灾难恢复的时机也将不再可能被吞噬,具体取决于您的SLA条款。
数据可用性
pg_auto_failover使用PostgreSQL同步复制来确保在故障转移操作时没有数据丢失。 sync rep Postgre功能可确保当客户端应用程序收到来自Postgres的COMMIT消息时,数据便将其发送到我们的辅助节点。
面对系统中任何一个ONE节点丢失的情况,pg_auto_failover可以正常工作。如果丢失了主服务器,然后又丢失了辅助服务器,那么除了备份之外,什么都没有。使用pg_auto_failover时,对于一次丢失多台服务器的情况,您仍然必须设置适当的灾难恢复解决方案。是的,这发生了。
还请注意臭名昭著的_file系统是否已满_,由于我们习惯于部署类似规格的服务器,因此它喜欢同时攻击主服务器和辅助服务器……
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
我克隆了一个rails仓库,我现在正尝试捆绑安装背景:OSXElCapitanruby2.2.3p173(2015-08-18修订版51636)[x86_64-darwin15]rails-v在您的Gemfile中列出的或native可用的任何gem源中找不到gem'pg(>=0)ruby'。运行bundleinstall以安装缺少的gem。bundleinstallFetchinggemmetadatafromhttps://rubygems.org/............Fetchingversionmetadatafromhttps://rubygems.org/...Fe
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案