[keycloak-dev] client query caches getting complicated

Marek Posolda mposolda at redhat.com
Wed Feb 17 15:09:07 EST 2016


On 17/02/16 18:11, Bill Burke wrote:
> Currently, adding or deleting a client, or updating a realm causes
> invalidation/eviction of the realm and all clients in that realm. To
> make matters worse, the next time the realm is accessed, it queries and
> loads each client and its relationships.  Why do we do this?  When a
> realm invalidation happens, the cache has no idea if the realm is just
> being updated or removed entirely from the DB. With a realm removal, you
> also need to evict the cache of all clients within the realm.  So, a
> cached realm MUST have a list of all clients within it.  As a result,
> the more clients that get added, keycloak gets slower and slower.
> Eventually though the cache stabilizes after inserts/update/deletes
> subside and we get back to normal performance, but you can see a nasty
> blip for a little bit.
We don't need to eagerly preload all clients when realm is loaded. 
Infinispan has streaming/predicate API and we are using it in many 
places (see InfinispanUserSessionProvider and all the stuff in package 
org.keycloak.models.sessions.infinispan.stream ). So when entry is 
invalidated, we can have cacheListener, which will query infinispan to 
return all cached clients of the realm and remove them. I can see that 
we already have listener. So possibly we can just change this line to 
use predicate query: 
https://github.com/keycloak/keycloak/blob/master/model/infinispan/src/main/java/org/keycloak/models/cache/infinispan/locking/LockingCacheRealmProviderFactory.java#L141


Other option is, that we can try to optimize eager preload and see if we 
can reduce number of SQL queries at startup. For example, it seems that 
CachedClient constructor sends SQL query to preload just realm roles. 
And then each client sends another SQL query to preload his client roles 
(method CachedClient.cacheRoles ). Couldn't we instead send one SQL 
query to load all roles of realm (both realm and client roles)? Maybe we 
can even send one big SQL query to load realm with all it's objects :-) 
Possibly some FetchType.EAGER in Hibernate entities could help here.

Marek
>
> I think i have a couple of solutions for this:
>
> * Create a separate client cache. Client keys would be
> "{realm.id}.{client.id}".  Iterate on all client keys, and evict those
> that start with the realm id.
> * Or, do a DB query for all clients of the realm.
>
> I'm giving this until end of day to see if I can get a good solution,
> otherwise i'm aborting.
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/keycloak-dev/attachments/20160217/34bdcefd/attachment.html 


More information about the keycloak-dev mailing list