[keycloak-dev] caching changes

Marek Posolda mposolda at redhat.com
Wed Feb 17 10:03:16 EST 2016


The thing is, when admin2 press "update realm" , the data on server are 
already updated from admin1. So he will see the value of 
"registrationEnabled" field is true and overrides it with his value false.

It seems the possibilitity to address this might be to add "version" 
column in DB. The version is sent to UI of admin console, but it's 
hidden. When admin2 press "update", he will send the version back and he 
will see that version in DB is bigger than expected, so someone updated 
realm in the meantime.

But I don't know if this is really issue which needs to be solved or 
rather corner case...

Marek

On 17/02/16 15:44, Bill Burke wrote:
> Even if you have caching off this is a problem.  You have to do this:
>
> * In RepresentationToModel, don't call setters on properties that have 
> equal values
> * If its not already set, change hibernate to optimized updates, don't 
> update fields that haven't changed
>
> On 2/17/2016 8:55 AM, Marek Posolda wrote:
>> Should this be done for user's cache too? Couldn't it happen that 
>> same user is concurrently updated by 2 threads?
>>
>> Also wonder about scenario like:
>> - 2 admin users are editing realm at the same time
>> - Admin1 enables user's registration for the realm and click "update"
>> - Admin2 changed access token timeout and then click "update" . AFAIK 
>> at this point, he overwrites the change by admin1 because we send 
>> whole realm representation in the request.
>>
>> Do we want to address this? Or is this rather a corner case?
>>
>> Marek
>>
>>
>> On 12/02/16 19:47, Bill Burke wrote:
>>> I'm still working on stuff, but here is a summary of things so far:
>>> * ConcurrenyTest is passing
>>> * Caching implementation is now a pessimistic locking style based on
>>> versions.  Locking never happens on reads, only writes.  There are two
>>> caches.  One cache holds the actual data, and is pretty much a vanilla
>>> invalidation cache.  The other cache olds versioning information and is
>>> a local-only cache and just is an id->version map.  Given an id, 
>>> what is
>>> the current version of it.  Hopefully, the implementation makes sure
>>> that you never are able to add or obtain a stale version of an object
>>> from the cache.  Locking happens for updates.  At the end of a
>>> transaction, all registered invalidations are iterated on, and a 
>>> version
>>> cache lock on that id is obtain.  The db is updated, and after that the
>>> locks are released.  A lock is also obtained whever something is added
>>> to the cache.  Again a lock is only obtained on the version cache, so
>>> any reads will never block.
>>> * KeycloakTransactionManager now has an enlistPrepare method.
>>> * There is a new RealmProvider.getClientByClientId() method. Clients 
>>> now
>>> have a clientId "index" in the cache.
>>> * There is a new RealmProvider.removeClient() method.  This was needed
>>> to support getClientByClientId()
>>>
>>> Some other things that were done:
>>> * Unnecessary @JoinTables were removed for certain @OneToMany 
>>> relationships.
>>> * getId() will no longer cause a DB query if you are invoking on a
>>> reference to a JPA adapter
>>> * RealmModel.getClients() and getClientNameMap() is no longer used to
>>> implement getClientByClientId() :)
>>> * CachedRealm now stores PrivateKey, PublicKey, and Certificate in a
>>> transient variable.  We were actually unmarshalling from the cached pem
>>> format every time these things were access, which is like few times per
>>> login.
>>>
>>> Next steps:
>>> * Create a client list cache for each realm.  Currently, if you
>>> add/remove a client, this invalidates the realm cache and its doing a
>>> big query for each client.
>>> *  Do some profiling to see if there's other things we can do.
>>>
>>
>



More information about the keycloak-dev mailing list