AxonFramework 关系型数据库性能优化指南
前言
AxonFramework 是一个强大的 CQRS 和事件溯源框架,当与关系型数据库结合使用时,合理的数据库配置对系统性能至关重要。本文将深入探讨如何优化 AxonFramework 在关系型数据库环境中的性能表现。
索引优化策略
事件存储表索引
对于 DomainEventEntry
表(存储领域事件的核心表),必须创建以下索引:
- 复合唯一索引:
aggregateIdentifier
+sequenceNumber
组合 - 事件ID索引:
eventIdentifier
字段(唯一索引)
这些索引能显著提升事件加载和聚合重建的性能。
快照表索引
对于 SnapshotEventEntry
表(存储聚合快照):
- 聚合ID索引:
aggregateIdentifier
字段 - 事件ID索引:
eventIdentifier
字段(唯一索引)
Saga相关表索引
Saga 实现需要特别注意以下索引:
- 关联值索引:
AssociationValueEntry
表的sagaType
+associationKey
+associationValue
组合 - Saga实例索引:
sagaId
+sagaType
组合
列类型优化建议
常见字段长度优化
- UUID字段:使用固定长度 CHAR(36) 而非 VARCHAR(255)
- 时间戳字段:UTC 时间戳使用固定长度 CHAR(24),其他时区最多需要 CHAR(28)
- 类型字段:聚合类型名称通常较短,VARCHAR(50) 通常足够
重要提示:强烈建议所有时间戳使用 UTC 格式存储,避免夏令时切换导致的事件排序问题。
自增序列配置
全局序列问题
AxonFramework 使用自增值来保证事件处理顺序,但需要注意:
- 插入顺序与提交顺序可能不同
- 序列间隙会影响处理性能
- 默认配置可能导致序列号分配过于激进
Hibernate 6+ 配置
在 Hibernate 6 中,默认序列分配大小增加到 50,这可能导致:
- 多租户环境下的唯一性问题
- 不必要的序列间隙
推荐配置:
<!-- META-INF/orm.xml 配置示例 -->
<entity-mappings version="1.0" xmlns="http://java.sun.com/xml/ns/persistence/orm">
<mapped-superclass access="FIELD" metadata-complete="false"
class="org.axonframework.eventhandling.AbstractSequencedDomainEventEntry">
<attributes>
<id name="globalIndex">
<generated-value strategy="SEQUENCE" generator="myGenerator"/>
<sequence-generator name="myGenerator"
sequence-name="mySequence" allocation-size="1"/>
</id>
</attributes>
</mapped-superclass>
</entity-mappings>
关键点:
- 设置
metadata-complete="false"
以覆盖而非替换注解 - 分配大小设为 1 以减少间隙
PostgreSQL 特殊优化
TOAST 与大型对象存储
PostgreSQL 处理大对象的两种方式:
- TOAST:自动压缩和分块存储(透明处理)
- Large Object Storage:使用 OID 引用外部存储(有额外开销)
Axon 中的 LOB 字段
Axon 在多处使用 @Lob
注解:
- 事件和快照的 payload 和 metadata
- Token 存储
- Saga 序列化数据
- 死信队列相关内容
默认情况下,Hibernate 会使用 OID 类型,这会导致:
- 额外的读取开销
- 更新时遗留垃圾数据
- 查询显示 OID 而非实际数据
优化方案
1. 自定义方言
public class ByteaEnforcedPostgresSQLDialect extends PostgreSQLDialect {
public ByteaEnforcedPostgresSQLDialect(){
super(DatabaseVersion.make(9, 5));
}
@Override
protected String columnType(int sqlTypeCode) {
return sqlTypeCode == SqlTypes.BLOB ? "bytea" : super.columnType(sqlTypeCode);
}
// 其他必要方法...
}
Spring 配置:
jpa.database-platform=your.package.ByteaEnforcedPostgresSQLDialect
2. ORM 映射覆盖
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm" version="2.0">
<entity class="org.axonframework.modelling.saga.repository.jpa.SagaEntry">
<attribute-override name="serializedSaga">
<column name="serializedSaga" column-definition="BYTEA"/>
</attribute-override>
</entity>
<!-- 其他实体覆盖... -->
</entity-mappings>
3. 数据迁移(如已有数据)
ALTER TABLE token_entry ADD COLUMN token_bytea BYTEA;
UPDATE token_entry SET token_bytea = lo_get(token);
ALTER TABLE token_entry DROP COLUMN token;
ALTER TABLE token_entry RENAME COLUMN token_bytea TO token;
数据库迁移工具集成
Liquibase 示例
databaseChangeLog:
- changeSet:
id: axon-framework-bootstrap
author: AxonIQ
changes:
- createTable:
tableName: token_entry
columns:
- column:
name: processor_name
type: VARCHAR(512)
constraints:
nullable: false
primaryKey: true
# 其他列定义...
# 其他表定义...
总结
通过合理配置索引、优化列类型、调整序列生成策略以及针对 PostgreSQL 的特殊优化,可以显著提升 AxonFramework 在关系型数据库环境中的性能表现。建议根据实际应用场景选择最适合的优化策略,并在生产环境部署前进行充分测试。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考