Hello @jdubois ,
I generate a monolithic application by JHipster. but I see that you use the NONSTRICT_READ_WRITE strategy for Hibernate second cache like the following:
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
but after searching, it seems that this strategy is not recommended byHibernate as the consistency is not guaranteed.
NONSTRICT_READ_WRITE: Cache is updated after a transaction that changed the affected data has been committed. Thus, strong consistency is not guaranteed and there is a small time window in which stale data may be obtained from the cache. This kind of strategy is suitable for use cases that can tolerate eventual consistency.
READ_WRITE: This strategy guarantees strong consistency which it achieves by using ‘soft’ locks: When a cached entity is updated, a soft lock is stored in the cache for that entity as well, which is released after the transaction is committed. All concurrent transactions that access soft-locked entries will fetch the corresponding data directly from the database
can you explain why you didn't use READ_WRITE Strategy? as its a better strategy. I feel that it's may cause a performance issue.
Best Regards.
For me it's a good compromise for performance vs consistency, at least for read-mostly applications (which is the majority of applications, but obviously not all applications).
You can have more information at:
https://vladmihalcea.com/how-does-hibernate-nonstrict_read_write-cacheconcurrencystrategy-work/
https://vladmihalcea.com/how-does-hibernate-read_write-cacheconcurrencystrategy-work/
I also don't think read_write is recommended by the Hibernate team, can you provide a link to this?
Closing as we had no comments for 2 weeks.
hi @jdubois ,
not meaning to reopen - but to clarify: I'm one of the engineers maintaining Hibernate and indeed I'd not recommend using NONSTRICT_READ_WRITE as a general default.
I would agree with you that it provides a good compromise in many cases; yet I'd recommend making sure users understand the compromise they are getting into. For defaults, a safer choice would be wise.
It also depends on the Caching technology actually used behind the scenes; for Quarkus as discussed on https://github.com/quarkusio/quarkus/issues/6492 using this level will produce an error, as the rather simple Cache implementation is only to be used for read only and/or immutable entities.
The cache we use is very efficient though: it's borrowing some technology from the Infinispan team combined with a core caching technology wrapping Caffeine - I just don't feel comfortable recommending such a non-distributed and non-transactional cache for anything else than local only caching of non-mutable data.
Hi @Sanne !
If you don't recommend using NONSTRICT_READ_WRITE, then I believe we should follow your recommendation, as you're the expert here. This choice was made very early in JHipster, and was my personal default at the time, but now we have many more users, it's different. I see many people just following what JHipster does, and trusting us to provide "safe defaults", when originally my idea was just to provide a template with the defaults I like, and have people modify them if needed.
Also, we are now supporting much more caching options: when this was made, we only had local Ehcache, and now we have a lot of distributed caching solutions.
Just to be fully sure: your recommendation would be "READ_WRITE", is that correct?
I'm reopening this so we don't forget about it. Then it's mostly discussing the best option, coding this should be trivial.
This has been opened for a long time, and I believe @Sanne is recommending READ_WRITE, so let's do it.
I'm going to do a PR for this, but a few comments first:
hi @jdubois ! Thanks for following up :+1:
While READ-WRITE is indeed a better defult than NONSTRICT_READ_WRITE, but the safest one is TRANSACTIONAL.
You could use TRANSACTIONAL but it's only supported by Ehcache and Infinispan (AFAIK). Not sure if that complicates things; I'm not complaining if you prefer to keep it simple and go with READ-WRITE.
Thanks @Sanne ! Indeed, I believe TRANSACTIONAL will not work with many of our caching options (like Redis, to take an obvious one). The idea is that we use a "safe" default, but also have that code generated so that people can easily see/understand/change it.
Most helpful comment
This has been opened for a long time, and I believe @Sanne is recommending
READ_WRITE, so let's do it.