Concurrency Issue on Hashmap Stored in Apache Ignite - caching

I am developing a Clustered Web Application with different WARS deployed, so I need session sharing (and not only this). I've started using Ignite as a good platform for Clustered(Replicated) cache server.
The issue I reached is this:
My cache Key is String and Value is a HashMap
CacheConfiguration<Integer, Map<String,String>> cfg = new CacheConfiguration<>("my_cache");
I am using this cache as a WEBSESSION. The issue is where one servlet gets the Map, Put some session specific values, and put it back to Ignite. After the first servlet gets the cache, second one enters and because it finishes after the first one, the second put will kill first one changes.
So my exact question is, what's the pattern to have concurrent map access issue solved is a high efficient way (without whole object locking).
Regards

It sounds a bit weird to me, because this scenario should be only possible when two there are two concurrent requests working with the same session. How is this possible?
But in any case, you can use TRANSACTIONAL cache for web session data. This will guarantee that these two requests will be processed within a lock and the data will be updated atomically.
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="web-sessions-cache"/>
<property name="atomicityMode" value="TRANSACTIONAL"/>
</bean>

Related

How can I disable ehcache or all types caching?

Hybris: 6.3.0.0-SNAPSHOT
I'm doing performance testing, and I need to disable caching. I've already disabled the database (mySQL) caching and would like to disable all forms of application caching. Is it possibe?
I've already seen other questions and the suggestion to use setDisableCaching for FlexibleSearch. Unfortunately, there are some FlexibleSearch that are under the control of Hybris, and I can't change the method directly. I'm looking to override it next, but I want to know if there's an easier way.
I've also tried adding "-Dnet.sf.ehcache.disabled=true" to tomcat.generaloptions in local.properties, but the application just seems to hang during startup, and the server never starts.
Additional context: We have a web service that is returing 3,000 PointOfService records. The first call is so slow, the Client thinks the application is not working (it might have timed out). The succeeding calls are faster, because the data has already been cached. I need to check how to improve the performance of the first call.
The new cache is Region Cache.
If you want to disable the cache you have to set the size of all regioncache to 0. It won't be really disabled but nothing will be cached.
You can disable it using code as mentionned in other response Registry.getCurrentTenant().getCache().setEnabled(false);
You can use old cache by setting in your local.properties cache.legacymode=true.
This won't disable all cache however.
Now if your problem is low time response when querying a lot of object maybe you need to define your own cache region and set the proper values in your properties :
<alias name="defaultMyObjectCacheRegion" alias="myObjectCacheRegion"/>
<bean name="defaultMyObjectCacheRegion" class="de.hybris.platform.regioncache.region.impl.EHCacheRegion">
<constructor-arg name="name" value="MyObjectCacheRegion" />
<constructor-arg name="maxEntries" value="${regioncache.myObjectcacheregion.maxentries}" />
<constructor-arg name="evictionPolicy" value="${regioncache.myObjectcacheregion.evictionpolicy}" />
<constructor-arg name="statsEnabled" value="${regioncache.stats.enabled}" />
<constructor-arg name="exclusiveComputation" value="${regioncache.exclusivecomputation}" />
<property name="handledTypes">
<array>
<value>[MyObject typecode]</value>
</array>
</property>
To conclude you should not try to disable hybris cache it's almost impossible. But you can easily clear it for testing purpose.
If you have performance issue, I suggest you also take a look a DB transaction. This is often a bottleneck. See : https://help.hybris.com/1808/hcd/8c7387f186691014922080f2e053216a.html
You can manually delete Hybris cache from-
https://localhost:9002/hac/monitoring/cache
Run the below as groovy script in commit mode from HAC
tenant.getCurrentTenant().getCache().setEnabled(false);
To reenable it, change false to true.
Did you consider adding a pagination to the call for PointOfService? Let the client request only 10/100 elements at a time. The client then can subsequently request the first 10, second 10... elements. That way the call will be a lot faster. It also wont cram your cache and stress server and database that much. Also the client will be much safer on his processing of the data.

Method caching with Spring boot and Hazelcast.How and where do I specify my refresh/reload intervals?

I realise #Cacheable annotation helps me with caching the result of a particular method call and subsequent calls are returned from the cache if there are no changes to arguments etc.
I have a requirement where I'm trying to minimise the number of calls to a db and hence loading the entire table. However,I would like to reload this data say every day just to ensure that my cache is not out of sync with the underlying data on the database.
How can I specify such reload/refresh intervals.
I'm trying to use Spring boot and hazelcast.All the examples I have seen talk about specifying LRU LFU etc policies on the config file for maps etc but nothing at a method level.
I can't go with the LRU/LFU etc eviction policies as I intend to reload the entire table data every x hrs or x days.
Kindly help or point me to any such implementation or docs etc.
Spring #Cacheable doesn't support this kind of policies at method level. See for example the code for CacheableOperation.
If you are using hazelcast as your cache provider for spring, you can explicitly evict elements or load datas by using the corresponding IMap from your HazelcastInstance.

Spring Integration Poller too slow

We have a Spring Integration project which uses a the following
<int-file:inbound-channel-adapter
directory="file:#{'${poller.landingzonepath}'.toLowerCase()}" channel="createMessageChannel"
filename-regex="${ingestion.filenameRegex}" queue-size="10000"
id="directoryPoller" scanner="leafScanner">
<!-- <int:poller fixed-rate="${ingestion.filepoller.interval:10000}" max-messages-per-poll="100" /> -->
<int:poller fixed-rate="10000" max-messages-per-poll="1000" />
</int-file:inbound-channel-adapter>
We also have a leafScanner which extends from the default RecursiveLeafOnlyDirectoryScanner, our leafscanner doesn't do too much. Just checks a directory against a regex property.
The issue we're seeing is one where there are 250,000 (.landed [the ones we care about] files) which means about 500k actual files in the directory that we are polling. This is redesign of an older system and the redesign was to make the application more scalable, whilst being agnostic of the directory names inside the polled parent directory. We wanted to get away from a poller per specific directory, but it seems unless we're doing something wrong, we'll have to go back to this.
If anyone has any possible solutions, or configuration items we could try please let me know. On my local machine with 66k .landed files, it takes about 16 minutes before the first file is presented to our transformer to do something.
As the JavaDocs indicate, the RecursiveLeafOnlyDirectoryScanner will not scale well with large directories or deep trees.
You could make your leafScanner stateful and, instead of subclassing RecursiveLeafOnlyDirectoryScanner, subclass DefaultDirectoryScanner and implement listEligibleFiles and return when you have 1000 files after saving off where you are; and on the next poll, continue from where you left off; when you get to the end, start again at the beginning.
You could maintain state in a field (which would mean you'd start over after a JVM restart) or use some persistence.
Just an update. The reason our implementation was so slow was beacuse of locking (trying to prevent duplicates), locking (preventing duplicates) is automatically disabled by adding a filter.
The max-messages-per-poll is also very important if you want to add a thread pool. Without this you will see no performance improvements.

How does infinispan know that it have to take the changes from delta aware object

We are using infinispan and in our system we have a big object in which we have to push small changes per transaction. I have implemented the DeltaAware interface for this object and also the Delta. The problem i am facing is that the changes are not getting propagated to other nodes and only the initial object state is prapogated to other nodes. Also the delta and commit methods are not called on the big object which implements DeltaAware. Do i need to register this object somewhere other than simply putting it in the cache ?
Thanks
It's probably better if you simply use an AtomicHashMap, which is a construction within Infinispan. This allows you to group a series of key/value pairs as a single value. Infinispan can detect changes in this AtomicHashMap because it implements the DeltaAware interface. AHM is a higher level construct than DeltaAware, and one that probably suits you better.
To give you an example where AtomicHashMaps are used, they're heavily used by JBoss AS7 HTTP session replication, where each session id is mapped to an AtomicHashMap. This means that we can detect when individual session data changes and only replicate that.
Cheers,
Galder

JPA2 Entities Caching

As it stands I am using a JSF request scoped bean to do all my CRUD operations. As I'm sure you most likely know Tomcat doesn't provide container managed persistence so in my CRUD request bean I am using EnityManagerFactory to get fold of enity manager. Now about the validity of my choice to use request scoped bean for this task, it's probably open for a discussion (again) but I've been trying to put it in the context of what I've read in the articles you gave me links to, specifically the first and second one. From what I gather EclipseLink uses Level 2 cache by default which stored cached entity. On ExlipseLink Examples - JPA Caching website it says that:
The shared cache exists for the duration of the persistence unit ( EntityManagerFactory, or server)
Now doesn't that make my cached entities live for a fraction of time during the call that is being made to the CRUD request bean because the moment the bean is destroyed and with it EntityManagerFactory then so is the cache. Also the last part of the above sentence "EntityManagerFactory, or server" gets me confused .. what precisely is meant by or server in this context and how does one control it. If I use the #Cache annotation and set appropriate amount of expire attribute, will that do the job and keep the entities stored on the servers L2 cache than, regardless of whether my EntityManagerFactory has been destroyed ?
I understand there is a lot of consideration to do and each application has specific requirements . From my point of view configuring L2 cache is probably the most desirable (if not only, on Tomcat) option to get things optimized. Quoting from your first link:
The advantages of L2 caching are:
avoids database access for already loaded entities
faster for reading frequently accessed unmodified entities
The disadvantages of L2 caching are:
memory consumption for large amount of objects
stale data for updated objects
concurrency for write (optimistic lock exception, or pessimistic lock)
bad scalability for frequent or concurrently updated entities
You should configure L2 caching for entities that are:
read often
modified infrequently
not critical if stale
Almost all of the above points apply to my app. At the heart of it, amongst other things, is constant and relentless reading of entities and displaying them on the website (the app will serve as a portal for listing properties). There's also a small shopping cart being build in the application but the products sold are not tangible items that come as stock but services. In this case stale entities are no problem and also, so I think, isn't concurrency as the products (here services) will never be written to. So the entities will be read often, and they will be modified infrequently (and those modified are not part of the cart anyway, an even those are modified rarely) and therefore not critical if stale. Finally the first two points seem to be exactly what I need, namely avoidance of database access to already loaded entities and fast reading of frequently accessed unmodified enteties. But there is one point in disadvantages which still concerns me a bit: memory consumption for large amount of objects. Isn't it similar to my original problem?
My current understanding is that there are two options, only one of which applies to my situation:
To be able to delegate the job of longer term caching to the persistence layer than I need to have access to PersistenceContext and create a session scoped bean and set PersistenceContextType.EXTENDED. (this options doesn't apply to me, no access to PersistenceContext).
Configure the L2 #Cache annotation on entities, or like in option 1 above create a session scoped bean that will handle long term caching. But aren't these just going back to my original problem?
I'd really like to hear you opinion and see what do you think could be a reasonable way to approach this, or perhaps how you have been approaching it in your previous projects. Oh, and one more thing, just to confirm.. when annotating an entity with #Cache all linked entities will be cached along so I don't have to annotate all of them?
Again all the comments and pointers much appreciated.
Thanks for you r answer .. when you say
"In Tomcat you would be best to have some static manager that holds onto the EntityManagerFactory for the duration of the server."
Does it mean I could for example declare and initialize static EntityManagerFactory field in an application scoped been to be later used by all the beans throughout the life of the application ?
EclipseLink uses a shared cache by default. This is shared for all EntityManagers accessed from an EntityManagerFactory. You do not need to do anything to enable caching.
In general, you do not want to be creating a new EntityManagerFactory per request, only a new EntityManager. Creating a new EntityManagerFactory is quite expensive, so not a good idea, even ignoring caching (it has its own connection pool, must initialize the meta-data, etc.).
In Tomcat you would be best to have some static manager that holds onto the EntityManagerFactory for the duration of the server. Either never close it, or close it when a Servlet is destroyed.

Resources