Keycloak 为高可用和多节点部署提供了基于 Infinispan 的分布式缓存。真正组成一个集群,需要同时满足三件事:节点使用一致的数据库与缓存配置,能通过发现机制找到彼此,并且缓存传输和故障检测链路能够互通。启动了多个进程,并不自动证明集群已经健康。
本文根据 Keycloak Team 的 Configuring distributed caches 译写,核对日期为 2026-10-05。指南版本选择器与 下载页 均标示 26.8.0;原文没有明确首次发表日期。本文围绕默认 jdbc-ping/TCP、内嵌 Infinispan 和持久会话展开,不将多站点、stateless、自定义传输栈或服务网格改造拼入常规部署步骤。
启用集群缓存,先分清生产与开发模式
用 start 进入生产模式时,Keycloak 默认启用分布式缓存,使用 jdbc-ping 栈:节点发现通过配置的数据库进行注册,节点间数据传输使用 TCP。要显式写出缓存模式,官方命令为:
bin/kc.[sh|bat] start --cache=ispn
这里 [sh|bat] 是文档对 Unix/Windows 脚本的合并写法,实际应选择 bin/kc.sh 或 bin\kc.bat。它不是一条可以原样交给 shell 的路径。这个命令只展示缓存选项,数据库、主机名和对外 HTTPS 等生产配置仍须按环境提供。
start-dev 隐式采用 --cache=local,完全禁用分布式缓存,仅适合开发与测试。若用它启动多个实例,看不到集群成员并不意外。数据库指南也明确指出默认 dev-file 仅适合开发,生产应明确选择受支持数据库;同一部署的节点需要连接同一数据库,不能各用自己的开发文件库。

缓存保存的究竟是什么
默认配置文件位于 conf/cache-ispn.xml,包含 cache-container 与 JGroups transport 的设置。不同缓存用途不同,不能笼统认为“所有 Keycloak 状态都只在内存里”。
| 缓存 | 类型 | 用途 |
|---|---|---|
realms |
本地 | 已持久化的 realm,以及客户端、角色、组等关联数据 |
users |
本地 | 用户及授予角色、组成员关系等关联数据 |
authorization |
本地 | 资源、权限、策略等授权数据 |
keys |
本地 | 外部客户端或身份提供方的公钥 |
crl |
本地 | X.509 认证器使用的证书吊销列表 |
work |
复制 | 向所有节点传播缓存失效消息 |
authenticationSessions |
分布式 | 登录认证过程中创建、完成或过期的认证会话 |
sessions、clientSessions |
分布式 | 数据库中用户会话与客户端会话的内存缓存 |
offlineSessions、offlineClientSessions |
分布式 | 离线用户/客户端会话的内存缓存 |
loginFailures |
分布式缓存名称 | 失败登录计数的特定兼容模式;当前默认存储位置见下文 |
actionTokens |
分布式 | 异步确认动作令牌的元数据,例如忘记密码邮件流程 |
realms、users、authorization 的本地缓存默认各容纳 10,000 项。keys 默认最多 1,000 项,默认每小时过期,因此会周期性重新下载公钥。更大的缓存通常减少数据库往返,但也占用更多内存;应按数据库规模评估,不把默认值当成容量保证。
本地缓存之所以能用于多节点,是因为节点更新共享数据库后会通过 work 复制缓存发送失效消息,让其他节点清除旧值。work 中消息寿命很短,正常情况下不应持续累积成一个不断增长的数据集。
认证会话在用户开始登录时创建,认证完成或超时后销毁。分布式 authenticationSessions 让后续请求即使转到其他节点,也能继续访问认证过程的数据。缓存文仍保留“优先会话亲和”的建议,但编者核对发现当前反向代理指南已经更新:26.6 优化之后,粘性会话的收益不足以抵消复杂代理配置,推荐把负载均匀分配给各节点。本文依据 当前 Sticky sessions 说明,不再把旧亲和建议作为优化结论。
失败登录数据在当前默认配置中存入数据库。多站点/clusterless 使用外部 Infinispan,而内嵌 loginFailures 缓存只作为显式启用已弃用 login-failures:v1 的后备模式。切换存储模式后,旧位置可能留下不会自动清理的计数;日后切回时可能重新生效。原文提醒需处理这些旧记录,本篇不执行清理,也不建议未经核对删除安全相关数据。
持久会话、内存容量与关闭缓存的取舍
用户会话跟踪一个用户在一个或多个应用中的登录,客户端会话对应应用侧状态;离线会话是由离线令牌支撑的长寿命会话。默认持久化模式下,这四类会话保存在数据库,按需加载到内嵌缓存。缓存中的条目可以被其他节点访问,从而减少数据库查询。
四种会话缓存默认每节点最多 10,000 项,每条记录使用一个 owner。可以通过对应最大项数选项调整,比如:
--cache-embedded-offline-sessions-max-count=1000
原文的通用表达是 --cache-embedded-${CACHE_NAME}-max-count=,实际 CLI 名称使用连字符。下表列出与本篇有关的缓存上限选项,值类型均为整数:
| 缓存 | CLI | 环境变量 |
|---|---|---|
| realms | --cache-embedded-realms-max-count |
KC_CACHE_EMBEDDED_REALMS_MAX_COUNT |
| users | --cache-embedded-users-max-count |
KC_CACHE_EMBEDDED_USERS_MAX_COUNT |
| authorization | --cache-embedded-authorization-max-count |
KC_CACHE_EMBEDDED_AUTHORIZATION_MAX_COUNT |
| keys | --cache-embedded-keys-max-count |
KC_CACHE_EMBEDDED_KEYS_MAX_COUNT |
| crl | --cache-embedded-crl-max-count |
KC_CACHE_EMBEDDED_CRL_MAX_COUNT |
| sessions | --cache-embedded-sessions-max-count |
KC_CACHE_EMBEDDED_SESSIONS_MAX_COUNT |
| clientSessions | --cache-embedded-client-sessions-max-count |
KC_CACHE_EMBEDDED_CLIENT_SESSIONS_MAX_COUNT |
| offlineSessions | --cache-embedded-offline-sessions-max-count |
KC_CACHE_EMBEDDED_OFFLINE_SESSIONS_MAX_COUNT |
| offlineClientSessions | --cache-embedded-offline-client-sessions-max-count |
KC_CACHE_EMBEDDED_OFFLINE_CLIENT_SESSIONS_MAX_COUNT |
actionTokens、authenticationSessions、loginFailures、work 不能按这套选项设置上限;原文该句把 actionTokens 拼成单数 actionToken,本文按其缓存总表统一名称。已弃用的 volatile 会话模式也不支持为 sessions/clientSessions 设置最大项数。
只在持久会话启用时,可用下面的 SPI 选项关闭会话内存缓存:
spi-user-sessions--infinispan--use-caches=false
这样可减少节点内存、节点间同步流量以及慢节点对请求的影响,但每次会话读取都转向数据库,尤其可能增加令牌内省和 token exchange 的数据库连接与 CPU 压力。原文预期数据库自身缓存可避免额外 IOPS;这是其设计说明,不是本文的基准测试结果,实际负载仍需测量。
从 26.8 起,只在内存保存普通用户会话的 volatile 模式已经弃用。原文建议移除 --features-disabled=persistent-user-sessions,回到默认持久化模式;旧 volatile 模式在所有节点重启后会丢失全部普通用户会话,活跃会话增多也会持续增加内存需求。本篇保持默认持久会话,不引入该旧分支。
使用受支持选项,避免把 XML 覆盖当作常规调优
Keycloak 会按预期配置创建所需缓存。虽然技术上可以修改 conf/cache-ispn.xml,或通过 --cache-config-file=my-cache-file.xml 选取自定义文件(可用绝对路径或相对 conf/ 的路径),原文明确指出:覆盖默认缓存配置的 XML 做法不受支持,只适合默认配置已证明有问题的高级场景。受支持的默认缓存修改方式是 cache-... 选项。
--cache-config-mutate=true 能抑制检测到默认配置被修改时的警告,但“警告消失”不等于方案获得支持。本文不提供 XML 覆盖步骤。需要查看真正生效的配置时,可临时增加这个日志分类:
--log-level=info,org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory:debug
调试日志应在受控环境收集,避免长期保留不必要的详细配置日志。本次仅阅读原文,没有生成或读取任何真实集群日志。
默认节点发现与集群标识
jdbc-ping 通过 JGroups JDBC_PING2 在数据库中维护节点发现信息,数据通道则是 TCP。启用分布式缓存时它就是默认值,与 26.x 默认行为向后兼容;无需为本篇另行选择旧的 DNS 或组播栈。
源页还列出 kubernetes、jdbc-ping-udp、tcp、udp、ec2、azure、google,但这些值均已弃用。旧 kubernetes 栈使用 DNS_PING 并需要无头服务 FQDN;tcp/udp 旧栈依赖组播,旧文档还列有 239.6.7.8 与 46655 的默认组播地址和端口。这些不是本篇 jdbc-ping/TCP 主线需要开放的组播配置。
默认集群名是 ISPN,同一部署节点应使用相同集群名。默认发现使用共享数据库,因此无意中共享数据库、又使用同名集群的两个部署可能合并。不过,不能简单把它们改成不同 --cache-embedded-cluster-name 就算完成隔离:原文警告,不同集群名之间的缓存失效不会自动传播,普通模式会出现陈旧缓存。不同名称的多集群方案应与 stateless 功能一起设计,超出本文范围。
节点名可以独立设置,例如 --cache-embedded-node-name=node-1,对应环境变量 KC_CACHE_EMBEDDED_NODE_NAME。默认每次启动生成随机名;稳定节点名更便于关联重启前后的日志与指标。它不会代替数据库、传输地址或成员健康检查。
默认 mTLS 的证书与轮换
TCP 缓存传输默认启用 TLS,不需要另改 XML 或增加启用参数。Keycloak 自动生成 RSA 2048 位自签名证书,使用 TLS 1.3 保护节点通信;密钥和证书保存在数据库,让所有节点可取得它们。默认有效期 60 天,运行中每 30 天轮换一次,可通过 --cache-embedded-mtls-rotation-interval-days 调整轮换间隔。
--cache-embedded-mtls-enabled 默认是 true,对应环境变量为 KC_CACHE_EMBEDDED_MTLS_ENABLED。这保护的是集群传输,不是浏览器到 Keycloak 的 HTTP 接口,也不代替网络访问控制。标准部署应保留默认密钥管理;源页同时提供 keystore/truststore 的 file/password 参数,但本文不手工配置或展示任何密钥和密码。
UDP/TCP_NIO2、自定义证书和 Istio 等服务网格有各自加密配置要求。原文提到服务网格拦截可能出现 JGRP000006: failed accepting connection from peer SSLSocket,原因之一是对端呈现了错误证书。不能为消除错误就直接关闭 mTLS;本篇不提供网格 PERMISSIVE 或绕过步骤,也不把远程 Infinispan 的 cache-remote-tls-enabled 与内嵌集群 mTLS 混为一谈。
两个必须核对的 TCP 端口
| 默认端口 | 用途 | 配置 |
|---|---|---|
| 7800 | 节点间单播缓存数据传输 | cache-embedded-network-bind-port / jgroups.bind.port |
| 57800 | FD_SOCK2 通过 socket 突然关闭等事件检测节点故障 | jgroups.fd.port-offset,默认在绑定端口上加 50000 |
如果改了 7800,也要重新计算故障检测端口,不要只放行数据通道。没有专用选项的 JGroups 属性,可通过 JAVA_OPTS_APPEND 或命令行中的 -D<property>=<value> 传递。
编者说明:这些端口应在可信集群成员之间互通,不应因为“需要开端口”就暴露到公网。管理和指标端口也与缓存端口不同;当前反向代理指南指出 9000 用于管理/健康/指标,不应作为普通公共反代端口。
绑定地址与跨网络地址通告
传输端口必须绑定到其他所有节点都能访问的接口。默认选择 SITE_LOCAL 地址,例如 192.168.0.0/16 或 10.0.0.0/8 内的地址。多网卡主机上,私有地址并不一定就是正确的集群网卡;必要时用 cache-embedded-network-bind-address=<IP> 明确指定。
| 值 | 含义 |
|---|---|
GLOBAL |
优先全局地址,不可用时回退 SITE_LOCAL |
SITE_LOCAL |
选择站点本地地址,默认值 |
LINK_LOCAL |
169.254.1.0 至 169.254.254.255 的链路本地地址 |
NON_LOOPBACK |
任意非回环地址 |
LOOPBACK |
回环地址,例如 127.0.0.1 |
match-interface:<regex> |
按接口名匹配,例如 match-interface:tun0 |
match-address:<regex> |
按地址匹配,例如文档中的 match-address:192.168.* |
match-host:<regex> |
按主机名匹配,例如 match-host:linux.* |
纯 IPv6 且让 Keycloak 自动选择绑定地址时,原文给出的 JVM 设置为:
export JAVA_OPTS_APPEND="-Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=true"
它会为该 shell 设置变量;如果已有其他 JVM 参数,应合并评估,避免不小心替换原值。本文没有实际修改任何环境变量。
若实例位于容器或不同网络,其他节点不能直接访问其本地 IP,需要由部署环境提供适当的转发路径。配置 cache-embedded-network-external-address 和 cache-embedded-network-external-port,让节点通告其他成员真正可达的地址与端口;仅在其不同于 bind 地址/端口时设置。写了通告值并不会自动创建网络转发规则,也不会自动解决防火墙或故障检测链路。
让副本分布认识故障域
Infinispan 可按拓扑分散数据副本。例如某缓存配置了 num_owners=2,会尽可能把两份数据放在不同节点或故障域。默认已持久化的用户/客户端会话有数据库保障,其他分布式缓存仍会受这些分布策略影响。
原文提供 site、rack、machine 三层标识。本文不展开多站点部署,但保留它们的用途:site 区分数据中心,rack 区分机架,machine 区分承载多个容器/虚拟机的物理机。同一故障域应一致,不同故障域的值应不同。对应选项是 spi-cache-embedded--default--site-name、--rack-name、--machine-name(后两项沿用相同 SPI 前缀)。例如:
--spi-cache-embedded--default--rack-name=rack-1
--spi-cache-embedded--default--machine-name=machine-1
Keycloak Operator 会依据 Kubernetes 节点自动设置 machine 名称。原文还建议通过反亲和或 topology spread constraints 减少多个 Pod 落在同一节点的情况。这些说明帮助理解故障域,不意味着本文已经配置了多副本数量、跨机架调度或跨站点高可用。
用三个视角确认集群真正形成
部署之后,需要把“预期节点数”与实际成员列表对照。官方提供以下三个观察入口。
- 管理界面:进入通常形如
https://<your-host>/admin/master/console/#/master/providers的页面,在 Provider Info 找到connectionsInfinispan,展开 Show more,检查集群状态和各缓存健康信息。管理界面应按环境限制访问。 - 日志:每当节点加入或离开,Infinispan 会记录新的 cluster view。搜索
ISPN000094,核对成员列表是否齐全。 - 指标:启用指标后,从 Prometheus 端点读取
vendor_cluster_size,确认值等于当前期望运行的实例数。
原文给出下面的两节点日志:
ISPN000094: Received new cluster view for channel ISPN: [node1-26186|1] (2) [node1-26186, node2-37007]
这里集群名为 ISPN,成员为 node1-26186 和 node2-37007,(2) 表示两名成员。这是官方示例,不是本次生成的日志。若预期三个实例,看到两名成员就仍需排查发现数据库、绑定/通告地址、两个 TCP 端口和 TLS 连接,不能仅凭页面可登录就认定高可用完整。
缓存指标与本篇的完成边界
启用 Keycloak 指标时,会自动暴露缓存指标。若需要延迟分布直方图,原文使用:
bin/kc.[sh|bat] start --metrics-enabled=true --cache-metrics-histograms-enabled=true
cache-metrics-histograms-enabled 默认 false,只在指标已启用时有效。采集直方图本身可能有性能代价,不宜在已经饱和的系统上未经评估直接启用。有关指标端点和集群指标的后续配置,应按官方 指标指南 继续核对。
本篇已核对缓存指南全文、版本和反代/数据库的相关边界,保留从启用到成员验证的完整主线。未安装 Keycloak、建立数据库、修改安全组、启动节点或采集指标;默认 mTLS 的介绍不是安全审计通过声明,图示也不是测试截图。原文另述远程 Infinispan、多站点、stateless、旧传输栈和自定义 XML 分支,本文按既定范围只说明它们的边界,不声称已完成这些部署。
来源归属:Keycloak Team;原页页脚标示 © Keycloak Authors 2026 / © 2026 The Linux Foundation,All rights reserved。保留来源与版本,不以项目软件开源许可替代文章许可。












暂无评论内容