7 Replies Latest reply on Mar 26, 2015 6:48 AM by Yair Ogen

    locking cache for updates

    Yair Ogen Expert

      I need to synchronize a cache value between nodes. I am using num-of-owners == 1 for each key. I assume that I need to use the transactions support right? can you reference me to documentation on how much this affects performance?

       

      Also - are transaction the way to go if I'm in  Java SE and not EE application? I basically need something like optimistic locking built-in. Also note: I am not using the cache as a layer in front of a DB. the in-memeory store is my source of truth (loosing data if node A fails - is fine).

        • 1. Re: locking cache for updates
          Pedro Ruivo Novice

          Hi Yair,

           

          Can you elaborate "synchronize a cache value between nodes"?

           

          With or without transaction support, we maintain data consistency.

           

          Cheers,

          Pedro

          • 2. Re: locking cache for updates
            Yair Ogen Expert

            I have a 2 node cluster with one owner per entry. My cache entry value is a complex object that contains a list of other objects among other things.

            I want to make sure the following doesn't happen:

             

            Node A reads cache entry. Gets list of size 4.
            Node B reads cache entry for the same key and also gets list of size 4.

             

            Node A adds an object to the list and in parallel node B does the same.

            Now each node updates the cache. We end up with list of size 5 while we really would have wanted size of 6.

            • 3. Re: locking cache for updates
              Pedro Ruivo Novice

              Hi,

               

              Yes, in your case you need transactions with pessimistic lock. You can synchronize your data by acquiring the lock before reading it. for example

               

              transactionManager.begin();
              cache.getAdvancedCache().lock("my-list"); //1 network round-trip to acquire the lock (if the value does not exists in the node)
              List<Object> list = cache.get("my-list"); //1 network round-trip (if the value does not exists in the node)
              list.add(newObject);
              cache.put("my-list", list); //local only operation
              transactionManager.commit(); //1 network round-trip to send the updates and release the lock (if the value does not exists in the node)
              

               

              You don't need to lock if you force a write lock in the read:

              List<Object> list = cache.getAdvancedCache().withFlags(FORCE_WRITE_LOCK).get("my-list");
              

               

              Another alternative that does not requires transactions is to use the replace() method, but I have no idea how the performance is. example

               

              do {
                   List<Object> oldList = cache.get("my-list");
                   List<Object> newList = copyListAndAddObject(oldList, newObject);
              } while(!cache.replace("my-list", oldList, newList));
              

               

              The get() and replace() have a single network round-trip if the value does not exists locally.

              1 of 1 people found this helpful
              • 4. Re: locking cache for updates
                Yair Ogen Expert

                Thanks.

                 

                Using transactions is faster than using replace?

                 

                what is the penalty on cache locks within the same node when using transactions? I.e. 2 threads on the same node what to update the cache and it is stored locally. And how would that compare, performance wise, with 2 threads updating the cache whilst it resides in another node?

                • 5. Re: locking cache for updates
                  Pedro Ruivo Novice

                  Yair Ogen wrote:

                  Using transactions is faster than using replace?

                  Unfortunately I can't answer that question because it depends on multiple factors (mainly the application workload). Theoretically speaking, if the list needs to be updated frequently, the transactional approach should be faster than the replace.

                   

                  Yair Ogen wrote:

                  what is the penalty on cache locks within the same node when using transactions? I.e. 2 threads on the same node what to update the cache and it is stored locally. And how would that compare, performance wise, with 2 threads updating the cache whilst it resides in another node?

                  If it is stored locally, the performance should be the same as acquiring java locks. If it is stored remotely, you need a network round trip to acquire the lock. With 2 threads, one of the requests is able to acquire the lock and another will block until it is released.

                  • 6. Re: locking cache for updates
                    Yair Ogen Expert

                    Wouldn't an optimistic lock be better in terms of performance if in the rare cases where the data is stale my code will retry?

                    • 7. Re: locking cache for updates
                      Yair Ogen Expert

                      @Pedro, would this configuration suffice for the creation of the TC Manager?

                       

                      transaction().transactionManagerLookup(new JBossStandaloneJTAManagerLookup()).lockingMode(LockingMode.PESSIMISTIC)