
Odoo 19 数据库横向扩展终极指南
Odoo 19的一个重要功能:PostgreSQL数据库的横向扩展,即在单个Odoo实例背后配置多个PostgreSQL服务器,从而实现横向扩展以分散数据库负载。
Odoo 19允许一个Odoo实例连接到一个主读写服务器和多个只读副本服务器,从而分散数据库负载。这种架构被认为是一个强大但复杂的解决方案,旨在作为优化应用代码和用尽纵向扩展选项后的“最后手段”。其实现依赖于PostgreSQL的原生流复制,可以配置为异步或同步。选择同步复制可以提高数据一致性,但会引入延迟和新的故障点。在Odoo内部的配置很简单,但需要仔细的代码管理,特别是要消除保存点(savepoints),并使用新的装饰器(@api.read_only)和控制器参数来正确路由事务。
1.1. 核心概念与原理
标准的Odoo架构由一个Odoo实例连接到单个服务器上的一个PostgreSQL实例组成。扩展通常通过“纵向”方式实现,即增加该服务器的CPU或RAM。
Odoo 19中引入的新架构允许更复杂的横向扩展设置:
- 多个Odoo服务器可以连接到PostgreSQL服务器集群。
- 在该集群中,有一个主读写服务器和一个或多个只读副本服务器。
- Odoo被配置为将所有写入操作发送到主服务器,并将只读操作路由到副本服务器,从而分摊CPU和磁盘I/O负载。
- 主要的技术挑战是确保数据一致性,即在一个RPC调用中写入的数据,即使这些调用被路由到不同的数据库服务器,也能立即在下一个RPC调用中被读取。
1.2. 先决条件和注意事项:
你真的需要启用这个特性吗?在实施横向扩展之前,认识到其复杂性并将其作为最后的优化步骤是至关重要的:
- 避免过度工程:不要仅仅因为它在技术上“很酷”就实施这个解决方案。复杂的系统容易在最不方便的时候崩溃。
- 首先优化应用代码:性能不佳的Python代码(例如,O(n²)复杂度)不会因为更强大的硬件而得到修复。代码优化应该永远是第一步。
- 数据库健康至上:在考虑多服务器设置之前,请确保数据库得到良好维护,拥有必要的索引、适当的存储配置和优化的服务器设置。
- 榨干纵向扩展:如果当前的数据库运行在性能不足的硬件上(比如树莓派),解决方案是升级到一个更强大的单一服务器,而不是增加更多性能不足的服务器。
1.3. 扩展方法的比较
功能纵向扩展(更大的服务器)横向扩展(更多的服务器)复杂度低。系统保持不变。高。配置复杂。维护易于维护。维护更难。调整大小难。需要复制整个数据库和配置。容易。在池中添加另一个相同的服务器即可。硬件需要越来越大且昂贵的硬件。需要多个标准、相同的硬件实例。知识大多数系统管理员都能理解。需要专业知识。
1.4. PostgreSQL配置详情
该实现完全使用原生的PostgreSQL功能,无需外部软件。
- 技术:PostgreSQL内置的流复制。
- 核心原则:
- 这不是一个多主节点(multi-master)解决方案。只有一个服务器可以接受写入操作。
- 这不会分割数据库大小。每个副本服务器必须存储整个数据库,并有足够的内存来有效缓存它。主要的好处是分割CPU负载和部分磁盘I/O。
- 服务器之间的网络延迟是一个关键的性能因素。
- 复制类型
- 异步复制:这是标准方法。主服务器将数据更改发送给副本,但不等待确认就完成事务。
- 同步复制:主服务器在收到COMMIT后,会写入数据并等待指定数量的同步副本确认提交后,才向应用程序返回成功。
- 配置:通过在PostgreSQL配置中添加两行来实现,定义
synchronous_commit级别并列出synchronous_standby_names。可以提供一个有序的服务器列表来定义故障转移优先级。 - 性能影响:应用程序的提交延迟现在由最慢的同步副本决定。
- 可靠性风险:这种配置引入了一种新的故障模式。如果集群被配置为要求在一定数量的服务器上进行提交(例如,一个主服务器和两个副本),并且其中两个服务器变得不可用,整个集群将无法处理写入操作。拥有可以在故障时自动提升为同步状态的异步节点是至关重要的。
- 建议:从异步复制开始,在切换到同步复制之前彻底监控系统。
1.5. Odoo配置与事务处理
配置Odoo以使用只读副本是通过添加两个命令行参数实现的:db_replica_host 和 db_replica_port。Odoo可以配置为只连接一个副本端点;要使用多个副本,需要在它们前面使用负载均衡器或DNS轮询。
- 事务完整性:一个Odoo RPC调用对应一个PostgreSQL事务。该事务中的所有查询必须在单个服务器上执行——要么是读写主服务器,要么是只读副本。不可能将一个事务拆分到多个服务器上。
- 识别只读事务:
- Web控制器:在web控制器的路由中添加参数
read_only=True会向Odoo发出信号,尝试在副本上执行。如果在此事务期间发生任何写入操作,就会抛出异常,Odoo会自动在读写主服务器上重试整个事务。这会导致性能损失。 - 模型方法:
@api.read_only装饰器可以应用于模型方法以实现相同的行为。 - 内置支持:版本19中已经有几个核心Odoo方法被标记为只读,包括
search_read、search_read_web_client和read。这意味着仅通过配置即可获得一些开箱即用的性能提升。
- Web控制器:在web控制器的路由中添加参数
- 故障处理:如果副本服务器变得不可用,Odoo将关闭连接并将所有请求重定向到读写主服务器。它将在默认的20分钟后尝试重新连接到副本。
1.6. 关键考量:保存点(Savepoints)的问题
自定义代码中对保存点的使用与此架构不兼容,必须移除。
- 原因:保存点生成的事务ID存储在一个64个条目的LRU缓存中。当这个缓存满时,第65个条目会写入磁盘文件。副本服务器不知道保存点何时被关闭,并不断检查磁盘以获取此文件,这会“扼杀性能”,因为它迫使不断进行磁盘读取而不是内存读取。



