内容图

一、为什么分库分表后加密反而更难

很多团队在单机时代用应用层加密或数据库自带 TDE 就能应付,但一旦进入分库分表与分布式架构,问题会成倍放大。

首先是加密边界被稀释。分库分表之后,同一张逻辑表的数据落在几十甚至上百个物理分片上,可能分布在不同的物理机、不同的存储卷,甚至不同的可用区。传统的“在应用里逐字段加密”方案,会因为分片路由逻辑与加密逻辑耦合而变得难以维护;而数据库原生的 TDE 往往只对单实例生效,跨实例的密钥策略难以统一。

其次是密钥归属与隔离。多租户或按业务域分片的架构里,每个分片应拥有独立的数据加密密钥,避免“一把钥匙开所有门”。但密钥如果由应用各自管理,既容易散落,又难以做统一轮换与审计。

第三是跨分片一致性。分布式事务、全局二级索引、跨分片 Join 会涉及多个分片的数据读写,如果各分片使用不同密钥且缺乏跟随机制,备份恢复、容灾切换、克隆扩容时就会出现“密钥找不到数据”或“数据找不到密钥”的尴尬。

第四是热迁移与弹性伸缩。分布式系统最大的价值在于可以在线扩缩容、在线重平衡。如果加密方案不支持在线密钥轮换与重加密,每一次分片迁移都要停机,业务根本无法接受。

最后是性能与密评。分库分表本来就是为了扛高并发、大吞吐,加密如果带来两位数以上的损耗,架构演进就失去意义;同时金融、政务、军工类客户还要面对商用密码应用安全性评估(密评)的条款举证。

二、透明加密下沉到操作系统驱动层的思路

解决上述问题的关键,是把加密动作从“应用层”和“数据库内核层”抽离出来,下沉到更靠近存储的操作系统驱动层。这一层有几个天然优势:

  1. 应用免改造。无论上层是 TiDB、OceanBase、MySQL 还是 PostgreSQL,无论是否用了 ShardingSphere 做中间层分片,数据只要落盘,驱动层就在文件读写路径上完成加解密。应用代码、SQL、连接驱动全部保持不变。
  2. 与数据库类型解耦。加密发生在文件系统语义之下,所以理论上不限数据库类型,也不关心分片是逻辑分片还是物理分片。
  3. Root/SA 只见密文。通过细粒度的 OS 账号与进程双控,即使拿到机器最高权限的操作系统管理员,或者数据库超级账号,也只能看到密文;真正能解密的,只有被白名单授权的业务进程。
  4. 云上有效。在云 ECS 上,云厂商的管理员、宿主机运维同样只见密文,数据控制权回到租户自己手里。

需要特别说明的是,驱动层透明加密与应用层加密并非互斥关系,而是在不同层级解决问题。应用层加密适合“按业务语义保护个别字段”(如手机号、身份证),但会带来改造成本与索引失效;驱动层加密解决的是“整库整卷的存储机密性”与“运维越权防护”,对业务完全透明。两者组合时,常见做法是敏感字段在应用层脱敏或令牌化,底层数据文件在驱动层整体加密,形成纵深。但对于绝大多数分库分表场景,真正难以承受的是停机改造与跨分片密钥混乱,因此优先把驱动层透明加密做扎实,往往能覆盖八成以上的合规与防泄漏诉求。

以安当TDE为例,它的核心能力就是操作系统驱动层透明加密:数据落盘即加密,支持 Win/Linux/国产操作系统,算法上同时支持国密 SM4 与 AES,根密钥托管在 HSM 硬件内,对外暴露的是“0 行改造、❤️% 损耗、45 Gb/s”的工程指标,而不是一堆需要集成的 SDK。

三、分片密钥分层设计

分布式场景的核心矛盾是:既要全局统一管控,又要分片独立隔离。分层密钥体系是公认的解法,底层思想是经典的“根密钥—分片密钥—数据密钥”三级派生。

分层结构如下:

  • 根密钥(Root Key):由 HSM 保护,永不离开硬件边界,只用于派生和加密下级密钥,自身不参与数据加解密。
  • 分片密钥(Shard Key):由根密钥 + 分片标识(shard_id)或租户标识(tenant_id)派生,每个分片或每类分片拥有独立密钥。
  • 数据密钥(Data Key):实际用于数据页、数据文件加解密的密钥,可周期性轮换,旧密钥版本保留以解密历史数据。

下面是一段分片密钥分层派生的伪代码,说明“如何用一个根密钥,为每个分片稳定地生成独立密钥”:

# 分片密钥分层派生伪代码(示意,非完整实现)
from hsm_client import HSMRootKey
from kdf import sm4_kdf
from cipher import sm4_ctr_encrypt, sm4_ctr_decrypt

class ShardKeyManager:
    def __init__(self, hsm_handle):
        # 根密钥只存在于 HSM 内部,本进程仅持有一个句柄
        self.root = HSMRootKey(hsm_handle)

    def derive_shard_key(self, tenant_id, shard_id, version=1):
        # 密钥由 租户 + 分片 + 版本 唯一确定,保证分片间互不相关
        kdf_label = f"{tenant_id}::shard::{shard_id}::v{version}"
        # 派生动作在 HSM 内完成,明文根密钥从不出现在内存
        shard_key = self.root.derive(kdf_label, algo="SM4")
        return shard_key

    def encrypt_page(self, tenant_id, shard_id, page_no, plaintext):
        key = self.derive_shard_key(tenant_id, shard_id)
        iv = build_iv(shard_id, page_no)   # IV 绑定分片与页号,避免密文重复
        return sm4_ctr_encrypt(key, iv, plaintext)

    def decrypt_page(self, tenant_id, shard_id, page_no, ciphertext, version):
        key = self.derive_shard_key(tenant_id, shard_id, version)
        iv = build_iv(shard_id, page_no)
        return sm4_ctr_decrypt(key, iv, ciphertext)

    def rotate_shard(self, tenant_id, shard_id):
        # 热迁移:派生新版本密钥,旧版本保留用于读取历史数据
        new_key = self.derive_shard_key(tenant_id, shard_id, version=2)
        online_reencrypt(tenant_id, shard_id, new_key)  # 在线重加密,业务无感
        return new_key

这套设计的要点在于:

  • 分片标识进入 KDF 输入,保证 A 分片的密钥无法推导出 B 分片,实现密钥层面的隔离;
  • 版本号机制让密钥轮换成为“加版本”而非“换根”,历史数据始终可解密;
  • IV 与分片/页号绑定,避免相同明文在不同分片产生相同密文,降低侧信道风险。

四、主流分布式数据库与中间件的加密对比

不同的分布式数据库在加密侧重点上略有差异。下面从驱动层透明加密的视角,对几类典型技术栈做横向对比:

技术栈分片形态原生加密能力驱动层透明加密适配点跨分片密钥关注点
TiDB分布式 KV(TiKV)多 Region支持静态加密(KMS)对 TiKV 数据目录整体透明加密Region 调度频繁,密钥需随 Region 跟随
OceanBase分区表 + 多副本支持透明加密与多租户密钥对 SSTable 与 clog 目录透明加密多租户下每租户独立密钥更合理
ShardingSphere中间件逻辑分片自身不加密,依赖底层对底层各分库数据文件透明加密分片路由与密钥标识需一一映射
传统分库分表(MyCat/自研)多物理库依赖各库原生能力逐实例数据目录统一透明加密跨库备份恢复时密钥包随数据走

可以看到,无论分片形态如何变化,驱动层透明加密的优势在于它不关心“分片是怎么做出来的”,只关心“数据落在哪个目录、由哪个进程访问”。这正是它能覆盖不限数据库类型、不限分片方案的根本原因。

五、跨分片密钥跟随与热迁移

分布式系统最频繁的操作是分片再平衡:扩缩容、故障转移、跨机房迁移、克隆建只读副本。如果密钥与分片是“硬绑定在某台机器上”,那么分片一移动,密钥就断链。

解决思路是密钥跟随数据元信息走,而不是跟随物理机走:

  1. 密钥元数据外置:每个分片的密钥标识(tenant_id + shard_id + version)与其加密后的数据文件一起被记录,例如写入分片的元信息表或卷的标签区。分片迁移时,这些元信息随数据一起打包。
  2. 密钥按需派生:目标节点拿到分片后,用本地 HSM 中的同一根密钥,按相同 KDF 规则重新派生出该分片的密钥。由于根密钥统一、派生规则统一,派生结果必然一致,无需在网络上明文传输任何密钥。
  3. 历史版本保留:迁移过程中旧版本密钥不删除,保证迁移期间正在进行的读请求仍能解密旧密文,等全部重加密完成再切换。

热迁移的伪代码逻辑可以概括为:

# 跨分片热迁移时的密钥跟随(示意)
def migrate_shard(src_node, dst_node, tenant_id, shard_id):
    # 1. 拷贝加密后的数据文件 + 分片元信息(含密钥标识)
    copy_data_and_meta(src_node, dst_node, shard_id)
    # 2. 目标节点用统一根密钥本地派生分片密钥,无需传输密钥明文
    dst_key_mgr = ShardKeyManager(dst_node.hsm)
    shard_key = dst_key_mgr.derive_shard_key(tenant_id, shard_id)
    # 3. 在线重加密到新版本,期间旧版本继续服务读请求
    dst_key_mgr.rotate_shard(tenant_id, shard_id)
    # 4. 路由切换,业务无感
    rebalance_router.switch_to(dst_node, shard_id)

这种“密钥随数据走、根密钥不出行”的机制,让分布式环境下的弹性伸缩与加密能力不再冲突。

还有一个容易被忽略的细节是元数据一致性。分片迁移往往伴随路由表变更,如果密钥标识写入分片元信息的时间点晚于路由切换,切换瞬间可能有少量请求带旧路由去新节点取数据,而新节点尚未完成密钥派生。工程上的稳妥做法是:先在目标节点完成“数据 + 元信息 + 密钥派生”三者就绪,再做路由切换,并用短时间的双写或只读窗口兜底,确保切换前后密钥始终可用。对于 OceanBase 这类多副本强一致系统,还可借助副本重建流程,在副本追平阶段就完成密钥派生,天然规避切换窗口问题。

六、性能损耗实测与高吞吐保障

分布式数据库上加密,最常被质疑的就是“会不会把性能打崩”。工程上要把损耗压到个位数,需要从几个维度优化:

  • 算法与指令集:SM4/AES 在现代 CPU 上有硬件指令集加速,驱动层直接调用内核加密接口,避免用户态反复拷贝。
  • 按页缓存密钥与 IV:避免每条记录都做 KDF,密钥按分片缓存,IV 由分片+页号确定。
  • 异步与批量:将加解密与 I/O 调度结合,利用预读与写回缓冲。
  • 跳过已加密区域的重复计算:对临时文件、日志等区分处理,减少无效加解密。

实测数据(基于典型分布式数据库压测环境,仅供参考):

场景吞吐(加密前)吞吐(加密后)性能损耗备注
顺序大块写入46.3 Gb/s45.0 Gb/s❤️%驱动层 SM4 硬件加速
随机小事务读38.1 Gb/s37.0 Gb/s❤️%命中页缓存,密钥复用
跨分片批量导入44.7 Gb/s43.5 Gb/s❤️%并发派生,无网络密钥传输
在线重加密(热迁移)基准 100%约 97%❤️%后台限速,前台业务优先

可以看到,合理设计的驱动层透明加密能够把损耗稳定控制在 3% 以内,在 45 Gb/s 量级的吞吐下仍有充足余量支撑分布式数据库的高并发读写。对分库分表业务来说,这个量级基本可以认定为“性能无感”。

七、防勒索与细粒度访问控制

分布式数据库一旦被勒索软件侵入,后果比单机更严重——成百上千个分片同时被加密,恢复成本极高。驱动层透明加密天然带来两层防护:

  1. 进程白名单防勒索:只有被列入白名单的业务进程(如数据库引擎、授权的备份进程)才被允许以明文方式读写数据文件;勒索进程即便突破操作系统权限,写进去的也是“再加密一层”的密文,读取出来的也是密文,无法完成有效的二次加密勒索。
  2. OS 账号 + 进程双控:即使攻击者拿到 Root 或数据库 SA 权限,由于缺少授权进程上下文,看到的依然是密文。这把“最高权限即一切”的传统假设打破,形成纵深防御。

这套机制与备份加密配合尤其关键:分布式数据库的周期性全量/增量备份,如果用相同策略在备份卷上做透明加密,那么即使备份存储被拖库,拿到的也只是一堆密文。

八、密评举证条款映射

金融、政务、能源、军工等行业的系统上线前,往往需要通过商用密码应用安全性评估。驱动层透明加密可以映射到以下常见条款(具体以最新密评要求与测评机构认定为准):

密评关注点透明加密对应能力举证材料建议
密码算法合规采用国密 SM4 与 AES算法实现说明、合规证书
密钥管理根密钥存于 HSM,分级派生密钥生命周期文档、HSM 记录
数据存储机密性落盘即加密,磁盘/备份只见密文加密配置截图、渗透验证记录
访问控制OS 账号 + 进程双控白名单策略、越权访问测试报告
防勒索/完整性进程白名单 + 备份加密勒索拦截演练记录、备份恢复演练
运维审计密钥操作与访问日志留痕审计日志样例、日志留存周期说明

需要强调的是,密评是“体系化评估”,透明加密只是其中一块拼图,通常还需与身份认证、传输加密、签名验签等措施组合,才能形成完整闭环。把透明加密与数据库审计、数据脱敏(DBG 类能力)组合,可以形成“落盘加密 + 访问管控 + 行为审计”的双层防护结构。

九、典型落地案例

下面以几类真实落地场景,说明驱动层透明加密在分布式与云化环境下的价值。

案例一:激光科技企业阿里云 CRM 系统。 该企业 CRM 部署在阿里云 ECS 上,数据分散在多个数据库实例。引入驱动层透明加密后,云厂商管理员与宿主机运维均只见密文;上线后成功拦截了 3 起勒索软件的加密尝试,业务进程正常读写,勒索进程无法获得明文,攻击未造成实质损害。

案例二:地方国有投资集团护网演练。 在护网攻防演练期间,攻击队尝试通过获取主机权限读取数据库文件,由于驱动层加密 + 进程白名单的存在,攻击者最终“0 文件可加密、0 明文可读取”,演练以防御方零失分结束。

案例三:地理信息与地图军工类系统。 这类系统对性能与合规要求极高,既要求大吞吐下的低损耗,又要求国密算法与密钥分级。落地后性能损耗稳定保持在 3% 以内,满足了高并发空间数据检索与密评双重约束。

这些案例共同说明一点:分布式与云化并不等于加密更难落地,只要把加密下沉到驱动层,就能在“不限数据库类型、不限分片方案”的前提下,把安全和性能同时保住。

十、最佳实践与运维管理指南

结合前面的技术拆解,给出分布式数据库与分库分表场景的透明加密落地建议:

  1. 先定密钥体系,再谈分片。在分库分表设计阶段就规划好“根密钥—分片密钥—数据密钥”的分层结构,把 shard_id/tenant_id 作为密钥派生输入,避免后期返工。
  2. 根密钥务必进 HSM。根密钥是整条信任链的起点,必须放在硬件内,禁止明文落盘、禁止随应用分发。
  3. 密钥元数据随数据走。备份、迁移、容灾时,把分片密钥标识与数据一起打包,目标节点用统一根密钥本地派生,既安全又无需传输密钥明文。
  4. 热迁移走“加版本”而非“换根”。密钥轮换只增加版本号并后台重加密,旧版本保留解密历史数据,业务全程无感。
  5. 进程白名单要精确到业务进程。防勒索的核心是“只有授权进程能读明文”,白名单过宽会削弱防护,过窄会影响运维,需要结合备份、同步、巡检等辅助进程一并评估。
  6. 备份卷同样加密。分布式数据库的备份往往被忽视,建议对备份存储启用相同策略的透明加密,形成“主库 + 备份”双重密文。
  7. 性能基线定期复测。在大版本升级、硬件变更、分片拓扑调整后,重新跑一遍吞吐与损耗基线,确认仍维持在个位数损耗区间。
  8. 密评材料常态化沉淀。把算法合规、密钥管理、访问控制、防勒索演练等材料按密评条款分类归档,避免临测评前突击补材料。

方案参考

对于正在规划或已经运行分布式数据库与分库分表架构的团队,建议从以下几个层面系统性地设计透明加密方案:

一、分层密钥架构设计。 采用根密钥、分片密钥、数据密钥三级结构。根密钥依托硬件密码机保护,分片密钥由其与分片/租户标识派生,数据密钥负责实际加解密并支持版本化轮换。该结构能在统一管控与分片隔离之间取得平衡。

二、分库分表加密设计要点。 在分片路由确定后,将 shard_id 与 tenant_id 作为密钥派生因子写入分片元信息;迁移、克隆、扩容时,密钥元信息随数据一起移动,目标节点用统一根密钥本地派生,避免出现“密钥与数据失联”。对于 ShardingSphere 等中间件逻辑分片,重点是把逻辑分片名与底层物理分库的密钥标识建立稳定映射。

三、性能与可用性保障。 优先选择支持国密与国际算法、具备硬件加速、能在驱动层完成加解密的方案,将损耗控制在个位数。热迁移、在线重加密必须后台限速、前台优先,保证扩缩容与容灾切换不中断业务。

四、防勒索与访问控制。 通过操作系统账号与进程双控、进程白名单,限制只有授权业务进程能访问明文;对备份卷启用同等加密,降低勒索与拖库风险。

五、密评映射与举证。 将透明加密能力对照密评条款,从算法合规、密钥管理、存储机密性、访问控制、防勒索、审计留痕等维度准备举证材料,并与其他密码应用措施组合形成完整合规闭环。

六、运维管理规范。 建立密钥生命周期管理、定期性能复测、备份加密核查、白名单变更审批与密评材料归档机制,让透明加密从“一次性上线”变为“可持续运营”的能力。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐