配置分布式缓存

了解如何配置缓存层

Keycloak 被设计用于高可用性和多节点集群部署。当前分布式缓存的实现是基于 Infinispan 构建的,Infinispan 是一个高性能、可分布式内存数据网格。

启用分布式缓存

当你在生产模式下启动 Keycloak 时,通过使用 start 命令,缓存会被启用,并且网络中的所有 Keycloak 节点都会被发现。

默认情况下,缓存使用 jdbc-ping 堆栈,它基于 TCP 传输,并使用配置的数据库来跟踪加入集群的节点。Keycloak 允许你从一组预定义的默认传输堆栈中选择,或者定义你自己的自定义堆栈,正如你将在本指南后面看到的那样。

要显式启用分布式 Infinispan 缓存,请输入此命令

bin/kc.[sh|bat] start --cache=ispn

当你在开发模式下启动 Keycloak 时,通过使用 start-dev 命令,Keycloak 仅使用本地缓存,并且通过隐式设置 --cache=local 选项完全禁用分布式缓存。local 缓存模式仅用于开发和测试目的。

配置缓存

Keycloak 提供了一个缓存配置文件,其中包含合理的默认设置,位于 conf/cache-ispn.xml

缓存配置是一个标准的 Infinispan 配置文件

下表概述了 Keycloak 使用的特定缓存。你在 conf/cache-ispn.xml 中配置这些缓存

缓存名称 缓存类型 描述

realms

本地

缓存持久化的 realm 数据

users

本地

缓存持久化的用户数据

authorization

本地

缓存持久化的授权数据

keys

本地

缓存外部公钥

crl

本地

X.509 身份验证器 CRL 的缓存

work

复制

在节点之间传播失效消息

authenticationSessions

分布式

缓存身份验证会话,这些会话在身份验证过程中创建/销毁/过期

sessions

分布式

缓存持久化的用户会话数据

clientSessions

分布式

缓存持久化的客户端会话数据

offlineSessions

分布式

缓存持久化的离线用户会话数据

offlineClientSessions

分布式

缓存持久化的离线客户端会话数据

loginFailures

分布式

跟踪失败的登录,欺诈检测

actionTokens

分布式

缓存操作令牌

缓存类型和默认值

本地缓存

Keycloak 在本地缓存持久化数据,以避免不必要的数据库往返。

以下数据使用本地缓存保存在集群中的每个节点本地

  • realms 和相关数据,如客户端、角色和组。

  • users 和相关数据,如授予的角色和组成员资格。

  • authorization 和相关数据,如资源、权限和策略。

  • keys

realms、users 和 authorization 的本地缓存默认配置为最多保存 10,000 个条目。本地密钥缓存默认可以保存最多 1,000 个条目,并默认为每小时过期一次。因此,密钥会被强制定期从外部客户端或身份提供商处下载。

为了实现最佳运行时并避免额外的数据库往返,你应该考虑查看每个缓存的配置,以确保最大条目数与你的数据库大小对齐。你可以缓存的条目越多,服务器需要从数据库获取数据的频率就越低。你应该评估内存利用率和性能之间的权衡。

本地缓存失效

本地缓存提高了性能,但在多节点部署中增加了一个挑战。

当一个 Keycloak 节点更新共享数据库中的数据时,所有其他节点都需要意识到这一点,以便它们从其缓存中使该数据失效。

work 缓存是一个复制缓存,用于发送这些失效消息。此缓存中的条目/消息非常短暂,你不应期望此缓存的大小随时间增长。

身份验证会话

每当用户尝试进行身份验证时,都会创建身份验证会话。一旦身份验证过程完成或由于达到其过期时间,它们将自动销毁。

authenticationSessions 分布式缓存用于存储身份验证会话以及在身份验证过程中与之关联的任何其他数据。

通过依赖可分布式缓存,身份验证会话可供集群中的任何节点使用,以便可以将用户重定向到任何节点而不会丢失其身份验证状态。但是,生产就绪型部署应始终考虑会话亲缘性,并倾向于将用户重定向到最初创建其会话的节点。通过这样做,你将避免节点之间不必要的状态转移,并提高 CPU、内存和网络利用率。

用户会话

一旦用户通过身份验证,就会创建一个用户会话。用户会话跟踪你的活动用户及其状态,以便他们可以无缝地向任何应用程序进行身份验证,而无需再次被要求提供凭据。对于用户使用客户端会话进行身份验证的每个应用程序,服务器可以跟踪用户通过身份验证的应用程序及其在每个应用程序上的状态。

每当用户执行注销、客户端执行令牌撤销或由于达到其过期时间时,用户和客户端会话都会自动销毁。

会话数据默认存储在数据库中,并按需加载到以下缓存中

  • sessions

  • clientSessions

通过依赖可分布式缓存,缓存的用户和客户端会话可供集群中的任何节点使用,以便可以将用户重定向到任何节点,而无需从数据库加载会话数据。但是,生产就绪型部署应始终考虑会话亲缘性,并倾向于将用户重定向到最初创建其会话的节点。通过这样做,你将避免节点之间不必要的状态转移,并提高 CPU、内存和网络利用率。

这些用于用户会话和客户端会话的内存缓存默认限制为每个节点 10000 个条目,这减少了大型安装中 Keycloak 的总体内存使用量。内部缓存将为每个缓存条目仅运行一个所有者。考虑内存消耗与数据库利用率之间的权衡,并为缓存设置不同的大小,编辑 Keycloak 的缓存配置文件 (conf/cache-ispn.xml) 以为这些缓存设置 <memory max-count="..."/>

易失性用户会话

默认情况下,用户会话存储在数据库中,并按需加载到缓存中。可以配置 Keycloak 仅将用户会话存储在缓存中,并最大限度地减少数据库利用率。

由于此设置中的所有会话都存储在内存中,因此存在两个与此相关的副作用

  • 当所有 Keycloak 节点重启时,会话丢失。

  • 内存消耗增加。

按照以下步骤启用此设置

  1. 由于缓存是用户和客户端会话的唯一真实来源,请配置缓存以不限制条目数量,并将每个条目复制到至少两个节点。为此,请使用以下更新编辑 Keycloak 的缓存配置文件 (conf/cache-ispn.xml),以用于 sessionsclientSessions 缓存

    • 删除 <memory max-count="..."/>

    • distributed-cache 标记的 owners 属性更改为 2 或更多

    sessions 缓存的最终配置示例如下所示。

    <distributed-cache name="sessions" owners="2">
        <expiration lifespan="-1"/>
    </distributed-cache>
  2. 使用以下命令禁用 persistent-user-sessions 功能

    bin/kc.sh start --features-disabled=persistent-user-sessions ...

当启用 multi-site 功能时,无法禁用 persistent-user-sessions

离线用户会话

作为 OpenID Connect 提供商,服务器还能够对用户进行身份验证并颁发离线令牌。与常规用户和客户端会话类似,当服务器在成功身份验证后颁发离线令牌时,服务器还会创建一个离线用户会话和一个离线客户端会话。

以下缓存用于存储离线会话

  • offlineSessions

  • offlineClientSessions

与常规用户和客户端会话缓存类似,离线用户和客户端会话缓存也默认限制为每个节点 10000 个条目。从内存中逐出的项目将在需要时按需从数据库加载。考虑内存消耗与数据库利用率之间的权衡,并为缓存设置不同的大小,编辑 Keycloak 的缓存配置文件 (conf/cache-ispn.xml) 以为这些缓存设置 <memory max-count="..."/>

密码暴力破解检测

loginFailures 分布式缓存用于跟踪有关失败登录尝试的数据。此缓存是暴力破解保护功能在多节点 Keycloak 部署中正常工作所必需的。

操作令牌

操作令牌用于用户需要异步确认操作的场景,例如在忘记密码流程发送的电子邮件中。actionTokens 分布式缓存用于跟踪有关操作令牌的元数据。

配置缓存最大大小

为了减少内存使用量,可以对给定缓存中存储的条目数设置上限。要指定缓存的上限,你必须提供以下命令行参数 --cache-embedded-${CACHE_NAME}-max-count=,其中 ${CACHE_NAME} 替换为你想要应用上限的缓存名称。例如,要对 offlineSessions 缓存应用 1000 的上限,你可以配置 --cache-embedded-offline-sessions-max-count=1000。以下缓存无法定义上限:actionTokenauthenticationSessionsloginFailureswork

配置缓存以实现高可用性

分布式缓存将缓存条目复制到集群中节点的一个子集,并将条目分配给固定的所有者节点。

每个分布式缓存,即数据的主要真实来源 (authenticationSessionsloginFailuresactionTokens),默认情况下有两个所有者,这意味着两个节点具有特定缓存条目的副本。非所有者节点查询特定缓存的所有者以获取数据。当两个所有者节点都离线时,所有数据都会丢失。

默认的所有者数量足以在至少三个节点的集群设置中承受 1 个节点(所有者)的故障。你可以自由更改所有者的数量,以更好地满足你的可用性要求。要更改所有者的数量,请打开 conf/cache-ispn.xml 并将分布式缓存的 owners=<value> 值更改为你期望的值。

指定你自己的缓存配置文件

要指定你自己的缓存配置文件,请输入此命令

bin/kc.[sh|bat] start --cache-config-file=my-cache-file.xml

配置文件相对于 conf/ 目录。

远程服务器的 CLI 选项

为了配置 Keycloak 服务器以实现高可用性和多节点集群部署,引入了以下 CLI 选项 cache-remote-hostcache-remote-portcache-remote-usernamecache-remote-password,从而简化了 XML 文件中的配置。一旦存在任何声明的 CLI 参数,则表示 XML 文件中不存在与远程存储相关的配置。

连接到不安全的 Infinispan 服务器

不建议在生产环境中禁用安全性!

在开发或测试环境中,启动不安全的 Infinispan 服务器更容易。对于这些用例,CLI 选项 cache-remote-tls-enabled 禁用 Keycloak 和 Infinispan 之间的加密 (TLS)。如果 Infinispan 服务器配置为仅接受加密连接,Keycloak 将无法启动。

CLI 选项 cache-remote-usernamecache-remote-password 是可选的,如果未设置,Keycloak 将在不提供任何凭据的情况下连接到 Infinispan 服务器。如果 Infinispan 服务器已启用身份验证,Keycloak 将无法启动。

传输堆栈

传输堆栈确保集群中的 Keycloak 节点以可靠的方式进行通信。Keycloak 支持广泛的传输堆栈

  • jdbc-ping (默认)

  • kubernetes

  • jdbc-ping-udp (已弃用)

  • tcp (已弃用)

  • udp (已弃用)

  • ec2 (已弃用)

  • azure (已弃用)

  • google (已弃用)

要应用特定的缓存堆栈,请输入此命令

bin/kc.[sh|bat] start --cache-stack=<stack>

当启用分布式缓存时,默认堆栈设置为 jdbc-ping,这与 Keycloak 26.x 版本流中的默认值向后兼容。

可用的传输堆栈

下表显示了可用的传输堆栈,除了使用 --cache-stack 运行时选项外,无需任何其他配置

堆栈名称 传输协议 发现

jdbc-ping

TCP

使用 JGroups JDBC_PING2 协议的数据库注册表。

jdbc-ping-udp (已弃用)

UDP

使用 JGroups JDBC_PING2 协议的数据库注册表。

下表显示了可用的传输堆栈,它们使用 --cache-stack 运行时选项和最少配置

堆栈名称 传输协议 发现

kubernetes

TCP

使用 JGroups DNS_PING 协议的 DNS 解析。它需要将 jgroups.dns.query 设置为无头服务 FQDN。

tcp (已弃用)

TCP

使用 JGroups MPING 协议的 IP 多播。请参阅下文,了解如何为每个集群配置唯一的 jgroups.mcast_addrjgroups.mcast_port

udp (已弃用)

UDP

使用 JGroups PING 协议的 IP 多播。请参阅下文,了解如何为每个集群配置唯一的 jgroups.mcast_addrjgroups.mcast_port

当使用 tcpudpjdbc-ping-udp 堆栈时,每个集群必须使用不同的多播地址和/或端口,以便它们的节点形成不同的集群。默认情况下,Keycloak 使用 239.6.7.8 作为 jgroups.mcast_addr 的多播地址,使用 46655 作为 jgroups.mcast_port 的多播端口。

使用 -D<property>=<value> 通过 JAVA_OPTS_APPEND 环境变量或在 CLI 命令中传递属性。

其他堆栈

建议使用上述可用堆栈之一。Infinispan 提供了其他堆栈,但如何配置它们不在本指南的范围之内。有关更多文档,请参阅 设置 Infinispan 集群传输自定义 JGroups 堆栈

保护传输堆栈

对于基于 TCP 的传输堆栈,默认启用使用 TLS 进行加密,这也是默认配置。只要你使用的是基于 TCP 的传输堆栈,就不需要额外的 CLI 选项或修改缓存 XML。

如果你使用的是基于 UDPTCP_NIO2 的传输堆栈,请按如下步骤配置传输堆栈的加密

  1. 将选项 cache-embedded-mtls-enabled 设置为 false

  2. 按照 JGroups 加密文档加密集群传输 中的文档进行操作。

启用 TLS 后,Keycloak 会自动生成自签名 RSA 2048 位证书以保护连接,并使用 TLS 1.3 来保护通信。密钥和证书存储在数据库中,因此所有节点都可以使用它们。默认情况下,证书有效期为 60 天,并在运行时每 30 天轮换一次。使用选项 cache-embedded-mtls-rotation-interval-days 来更改此设置。

提供你自己的密钥和证书

尽管不建议用于标准设置,但如果在特定设置中至关重要,你可以手动配置包含传输堆栈证书的密钥库。cache-embedded-mtls-key-store-file 设置密钥库的路径,cache-embedded-mtls-key-store-password 设置解密密钥库的密码。信任库包含接受连接的有效证书,可以使用 cache-embedded-mtls-trust-store-file(信任库的路径)和 cache-embedded-mtls-trust-store-password(解密信任库的密码)进行配置。为了限制未经授权的访问,请始终为每个 Keycloak 部署使用自签名证书。

网络端口

为了确保 Keycloak 集群的健康运行,需要打开一些网络端口。下表显示了 jdbc-ping 堆栈需要打开的 TCP 端口,以及通过这些端口的流量描述。

端口 属性 描述

7800

jgroups.bind.port

单播数据传输。

57800

jgroups.fd.port-offset

协议 FD_SOCK2 的故障检测。它监听套接字的突然关闭以怀疑 Keycloak 服务器故障。jgroups.fd.port-offset 属性定义了相对于 jgroups.bind.port 的偏移量。

使用 -D<property>=<value> 在你的 JAVA_OPTS_APPEND 环境变量或 CLI 命令中修改上述端口。

网络绑定地址

为了确保 Keycloak 集群的健康运行,网络端口必须绑定到可以从集群的所有其他节点访问的接口上。

默认情况下,它会选择站点本地(不可路由)IP 地址,例如,来自 192.168.0.0/16 或 10.0.0.0/8 地址范围。

要覆盖该地址,请设置 jgroups.bind.address 属性。

使用 -Djgroups.bind.address=<IP> 在你的 JAVA_OPTS_APPEND 环境变量或 CLI 命令中修改绑定地址。

要设置为仅 IPv6 并让 Keycloak 自动选择绑定地址,请使用以下设置

export JAVA_OPTS_APPEND="-Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=true"

在不同网络上运行实例

如果你在不同的网络上运行 Keycloak 实例,例如在防火墙或容器后面,则不同的实例将无法通过其本地 IP 地址相互访问。在这种情况下,请为它们的本地 IP 地址设置端口转发规则(有时称为“虚拟服务器”)。

当使用端口转发时,请使用以下属性,以便每个节点都正确地将其外部地址通告给其他节点

属性 描述

jgroups.external_port

Keycloak 集群中的其他实例应使用此端口来联系此节点。

jgroups.external_addr

Keycloak 集群中的其他实例应使用此 IP 地址来联系此节点。

使用 -D<property>=<value> 在你的 JAVA_OPTS_APPEND 环境变量或 CLI 命令中设置此属性。

从缓存中公开指标

当指标启用时,缓存中的指标会自动公开。

要为缓存指标启用直方图,请将 cache-metrics-histograms-enabled 设置为 true。虽然这些指标提供了对延迟分布的更深入了解,但收集它们可能会对性能产生影响,因此你应该谨慎地在已经饱和的系统中激活它们。

bin/kc.[sh|bat] start --metrics-enabled=true --cache-metrics-histograms-enabled=true

有关如何启用指标的更多详细信息,请参阅 通过指标获得洞察力

相关选项

cache

定义高可用性的缓存机制。

在生产模式下,默认使用 ispn 缓存来创建多个服务器节点之间的集群。在开发模式下,默认使用 local 缓存禁用集群,仅用于开发和测试目的。

CLI: --cache
Env: KC_CACHE

ispn (默认), local

cache-config-file

定义应从中加载缓存配置的文件。

配置文件相对于 conf/ 目录。

CLI: --cache-config-file
Env: KC_CACHE_CONFIG_FILE

cache-metrics-histograms-enabled

为嵌入式缓存的指标启用直方图。

CLI: --cache-metrics-histograms-enabled
Env: KC_CACHE_METRICS_HISTOGRAMS_ENABLED

仅当指标启用时可用

true, false (默认)

cache-stack

定义用于集群通信和节点发现的默认堆栈。

CLI: --cache-stack
Env: KC_CACHE_STACK

仅当 'cache' 类型设置为 'ispn' 时可用

使用 'jdbc-ping' 代替 已弃用值: azure, ec2, google, tcp, udp, jdbc-ping-udp

jdbc-ping (默认), kubernetes, jdbc-ping-udp (已弃用), tcp (已弃用), udp (已弃用), ec2 (已弃用), azure (已弃用), google (已弃用), 或 any

嵌入式缓存

cache-embedded-authorization-max-count

授权缓存可以内存存储的最大条目数。

CLI: --cache-embedded-authorization-max-count
Env: KC_CACHE_EMBEDDED_AUTHORIZATION_MAX_COUNT

cache-embedded-client-sessions-max-count

clientSessions 缓存可以内存存储的最大条目数。

CLI: --cache-embedded-client-sessions-max-count
Env: KC_CACHE_EMBEDDED_CLIENT_SESSIONS_MAX_COUNT

仅当配置了嵌入式 Infinispan 集群时可用

cache-embedded-crl-max-count

crl 缓存可以内存存储的最大条目数。

CLI: --cache-embedded-crl-max-count
Env: KC_CACHE_EMBEDDED_CRL_MAX_COUNT

cache-embedded-keys-max-count

keys 缓存可以内存存储的最大条目数。

CLI: --cache-embedded-keys-max-count
Env: KC_CACHE_EMBEDDED_KEYS_MAX_COUNT

cache-embedded-mtls-enabled

加密 Keycloak 服务器之间的网络通信。

如果未提供有关密钥库和信任库的其他参数,则会自动创建和轮换临时密钥对和证书,这对于标准设置是推荐的。

CLI: --cache-embedded-mtls-enabled
Env: KC_CACHE_EMBEDDED_MTLS_ENABLED

仅当使用基于 TCP 的 cache-stack 时可用

true (默认), false

cache-embedded-mtls-key-store-file

密钥库文件路径。

密钥库必须包含 TLS 协议使用的证书。默认情况下,它在 conf/ 目录下查找 cache-mtls-keystore.p12

CLI: --cache-embedded-mtls-key-store-file
Env: KC_CACHE_EMBEDDED_MTLS_KEY_STORE_FILE

仅当启用属性 'cache-embedded-mtls-enabled' 时可用

cache-embedded-mtls-key-store-password

访问密钥库的密码。

CLI: --cache-embedded-mtls-key-store-password
Env: KC_CACHE_EMBEDDED_MTLS_KEY_STORE_PASSWORD

仅当启用属性 'cache-embedded-mtls-enabled' 时可用

cache-embedded-mtls-rotation-interval-days

自动 JGroups MTLS 证书的轮换周期(天)。

CLI: --cache-embedded-mtls-rotation-interval-days
Env: KC_CACHE_EMBEDDED_MTLS_ROTATION_INTERVAL_DAYS

仅当启用属性 'cache-embedded-mtls-enabled' 时可用

30 (默认)

cache-embedded-mtls-trust-store-file

信任库文件路径。

它应包含受信任的证书或签署证书的证书颁发机构。默认情况下,它在 conf/ 目录下查找 cache-mtls-truststore.p12

CLI: --cache-embedded-mtls-trust-store-file
Env: KC_CACHE_EMBEDDED_MTLS_TRUST_STORE_FILE

仅当启用属性 'cache-embedded-mtls-enabled' 时可用

cache-embedded-mtls-trust-store-password

访问信任库的密码。

CLI: --cache-embedded-mtls-trust-store-password
Env: KC_CACHE_EMBEDDED_MTLS_TRUST_STORE_PASSWORD

仅当启用属性 'cache-embedded-mtls-enabled' 时可用

cache-embedded-offline-client-sessions-max-count

offlineClientSessions 缓存可以内存存储的最大条目数。

CLI: --cache-embedded-offline-client-sessions-max-count
Env: KC_CACHE_EMBEDDED_OFFLINE_CLIENT_SESSIONS_MAX_COUNT

仅当配置了嵌入式 Infinispan 集群时可用

cache-embedded-offline-sessions-max-count

offlineSessions 缓存可以内存存储的最大条目数。

CLI: --cache-embedded-offline-sessions-max-count
Env: KC_CACHE_EMBEDDED_OFFLINE_SESSIONS_MAX_COUNT

仅当配置了嵌入式 Infinispan 集群时可用

cache-embedded-realms-max-count

realms 缓存可以内存存储的最大条目数。

CLI: --cache-embedded-realms-max-count
Env: KC_CACHE_EMBEDDED_REALMS_MAX_COUNT

cache-embedded-sessions-max-count

sessions 缓存可以内存存储的最大条目数。

CLI: --cache-embedded-sessions-max-count
Env: KC_CACHE_EMBEDDED_SESSIONS_MAX_COUNT

仅当配置了嵌入式 Infinispan 集群时可用

cache-embedded-users-max-count

users 缓存可以内存存储的最大条目数。

CLI: --cache-embedded-users-max-count
Env: KC_CACHE_EMBEDDED_USERS_MAX_COUNT

远程缓存

cache-remote-host

外部 Infinispan 集群的主机名。

仅当设置了功能 multi-siteclusterlesscache-embedded-remote-store 时可用。

CLI: --cache-remote-host
Env: KC_CACHE_REMOTE_HOST

cache-remote-password

用于身份验证到外部 Infinispan 集群的密码。

如果连接到不安全的外部 Infinispan 集群,则它是可选的。如果指定了此选项,则 cache-remote-username 也为必需。

CLI: --cache-remote-password
Env: KC_CACHE_REMOTE_PASSWORD

仅当设置了远程主机时可用

cache-remote-port

外部 Infinispan 集群的端口。

CLI: --cache-remote-port
Env: KC_CACHE_REMOTE_PORT

仅当设置了远程主机时可用

11222 (默认)

cache-remote-tls-enabled

启用 TLS 支持以与安全的远程 Infinispan 服务器通信。

建议在生产环境中启用。

CLI: --cache-remote-tls-enabled
Env: KC_CACHE_REMOTE_TLS_ENABLED

仅当设置了远程主机时可用

true (默认), false

cache-remote-username

用于身份验证到外部 Infinispan 集群的用户名。

如果连接到不安全的外部 Infinispan 集群,则它是可选的。如果指定了此选项,则 cache-remote-password 也为必需。

CLI: --cache-remote-username
Env: KC_CACHE_REMOTE_USERNAME

仅当设置了远程主机时可用

在本页