keycloak目前提供了几种分布式缓存,我们自己的缓存,如果希望是分布式的,可以将缓存添加到以下几个缓存里即可
- actionTokens
- clientSessions
- loginFailures
- offlineClientSessions
- offlineSessions
- sessions
- work
如果你希望自己开发分布式缓存,还是需要复杂的,需要配置,检查,获取远程分布式缓存的代码,比较复杂,有兴趣的同学,可以查看keycloak源代码,关于keycloak-model-infinispan
项目的实现。
直接使用现有分布式缓存
下面代码,将在现有的work缓存里,添加自己的缓存hello,后缀是用户ID,生命周期是access_token的有效期秒数
// 获取 Infinispan 连接提供程序和缓存领域提供程序
InfinispanConnectionProvider connectionProvider =
keycloakSession.getProvider(InfinispanConnectionProvider.class);
String key = "hello_" + userId;
if (connectionProvider.getCache("work") != null) {
int life=keycloakSession.getContext().getRealm().getAccessTokenLifespan();
connectionProvider.getCache("work").put(key, "ok", life, TimeUnit.SECONDS);
}
注意,上面代码只有第一次使用缓存时才会在集群上初始化,如果希望修改现有缓存的内容,它是不会进行初始化的,需要我们通过广播(发布/订阅)的方式通知其它节点
缓存的广播消息
# 注册
keycloakSessionFactory.register((ProviderEvent event1) -> {
if (event1 instanceof PostMigrationEvent) {
KeycloakModelUtils.runJobInTransaction(keycloakSessionFactory, session -> {
InfinispanConnectionProvider provider = session.getProvider(InfinispanConnectionProvider.class);
ClusterProvider cluster = session.getProvider(ClusterProvider.class);
cluster.registerListener(WECHAT_WORK_EVENT, (ClusterEvent event) -> {
if (event instanceof FanoutEvent) {
FanoutEvent fanoutEvent = (FanoutEvent) event;
System.out.println("registerListener收到事件订阅");
if (StringUtils.isNotBlank(fanoutEvent.getType())) {
provider.getCache(REALM_CACHE_NAME).remove(fanoutEvent.getType());
}
}
});
});
}
});
# 发布
ClusterProvider cluster = session.getProvider(ClusterProvider.class);
FanoutEvent fanoutEvent = new FanoutEvent();
cluster.notify(WECHAT_WORK_EVENT,fanoutEvent , false, ClusterProvider.DCNotify.ALL_DCS);
缓存模式
Infinispan支持四种缓存模式:本地(Local)模式、复制(Replicated)模式、失效(Invalidation)模式、分布式(Distribution)模式。除本地模式外,其他三种模式均为集群模式缓存。
3.1 本地模式
本地模式下,数据缓存在本地内存,节点间数据不共享。Infinispan的cache对象继承自Java的ConcurrentMap,和直接采用map相比,其优势在于:
支持缓存数据持久化,支持mongodb、leveldb等多种数据库。Infinispan通过设置cache store仅将将上述数据库作为缓存数据的存储介质,并不涉及数据库本身的其他高级特性。
支持eviction策略,避免内存耗尽。
支持expiration策略,保证长期未被使用的数据被清除。
基于MVCC的并发处理策略,采用CAS和其他lock-free算法保证高性能。
*事务性保证。
3.2 失效模式
失效模式下,数据需持久化到数据库(或其他持久化设备)中,节点间并不共享任何数据。当发生数据更新时,更新数据库并通知其他节点该数据已过期。节点发现数据过期后,采用lazy策略从数据库更新至缓存。这样做的好处在于:
- 网络负荷最小化。和复制模式下更新数据相比,失效消息要小的多,有效降低了网络负荷。
- 延迟更新。节点发现数据失效后,无需立即更新数据,仅当需访问该数据时才执行更新。
- 支持同步、异步两种失效方式。
- 同步失效:发送失效通知,并等待所有节点响应(收到失效消息,并逐出过期数据)后返回。
- 异步失效:发送失效通知,广播至所有节点,并直接返回。
- 数据存在持久化需求,缓存作为持久数据的中间层。在读操作频繁的场景下,采用Infinispan,避免每次直接访问数据库,提高读取性能。
3.3 复制模式
- 复制模式是集群模式的一种,在该模式任何一个节点的数据变更将复制到其他所有节点上,这使得集群中任何一个节点都包含了完整的缓存数据。
- 和嵌入式模式组合时,所有数据均保存在应用程序本地,读操作仅需访问本地内存,性能最高。
- 和C\S模式组合时,因为数据都保存在远端,读写都需要进行一次远端访问,此时复制模式和分布式模式相比并无明显优势。
- Infinispan设计了同步、异步两种方式用于将本节点的数据变更操作通知到其他节点,对于每种操作又支持TCP、UDP两种通信方式。采用UDP协议时,通过叠加JGroups的NAKACK2和UNICAST3保证传输的可靠性,具体可参见[JGroups支持]。
3.4 分布式(Distributed)模式
分布模式是Infinispan支持的可扩展性最好的一种模式。在这种模式下,用户可以配置固定数量(numOwners)的副本数,而不需要复制数据到所有的节点上。复制有限个副本既可以控制开销,也可以带来数据访问性能和可靠性的提升。
在集群中,Infinispan通过一致性哈希(Consistent Hashing)算法来确定数据访问和存储的位置。使用一致性哈希是好处是:当现有节点失效或新节点加入时,系统不需要重新计算哈希来重新分配数据在集群中的存储位置。
和复制模式相比,优势如下:
可扩展性:对集群节点数量没有限制,可根据业务需要,灵活的增、删节点。
数据网格:假设集群中有三个节点A,B,C,内存大小为8G,复制模式下集群容量为8G。分布式模式下,如果每个条目保存在2个节点上,集群的容量为(8 G* 3) / 2 = 12G。
和复制模式一样,分布式模式也支持同步和异步两种模式文章来源:https://www.toymoban.com/news/detail-746682.html
文章来源地址https://www.toymoban.com/news/detail-746682.html
到了这里,关于keycloak~分布式缓存的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!