This discussion is archived
10 Replies Latest reply: Sep 27, 2013 4:04 AM by alexey.ragozin RSS

Check if entry is persisted without check it on database

agentil Newbie
Currently Being Moderated

Hi,

 

Is there a way to check if an entry already was persisted to database (we use write-behind) without to check ORM "load/" method throw CacheStore?

We have a problem because removing an entry is a synchronous process and as we have configured a CacheStore, Coherence trys to remove entry on database even if it wasn't persisted.

We can use com.tangosol.util.InvocableMap.Entry.remove(false) that just removes from cache, but how can we guaranteed that entry is not persisted?

 

 

 

Thanks!

 

Best regards,

André

  • 1. Re: Check if entry is persisted without check it on database
    alexey.ragozin Explorer
    Currently Being Moderated

    Hi,

     

    Entries to be written to database are marked using binary decoration.

    You can find a snippet of code during this at my blog Alexey Ragozin: Coherence write behind, finding not-yet-stored entries.

     

    Regards,

    Alexey

  • 2. Re: Check if entry is persisted without check it on database
    jcpsantos Newbie
    Currently Being Moderated

    Hi Alexey,

     

    That is close but not exactly what we need. That DECO basically tells us if there is a pending store for the entry.

    1 - if you check the DECO on a new entry, it will exist;

    2 - if you check the DECO after the entry is stored, it will not exist;

    3 - if you check the DECO after the entry is stored and again updated, it will exist;

    4 - if you check the DECO on a loaded entry, it will not exist;

     

    What we need to know is if the entry exists in database without checking the database (we would need to differentiate entries on state 1 from entries on state 2, 3, and 4). Does Coherence keep a DECO for entries that it knows they exist on the database? Basically this DECO would exist on any entry that:

    1 - coherence loaded from the database;

    2 - coherence stored on the database;

     

    Thanks

  • 3. Re: Check if entry is persisted without check it on database
    alexey.ragozin Explorer
    Currently Being Moderated

    Well,

     

    You can add a trigger which could add your application specific DECO on insert event (let's call it DECO_NEW).

     

    1. DECO_STORE=false + DECO_NEW -> this is new entry and Coherence has not confirmed insert to DB yet

    2. DECO_STORE=false -> this is updated existing entry and Coherence has not confirmed DB update yet

    3. DECO_NEW -> this is new entry and Coherence has confirmed insert

    4. no decos -> entry is existing in DB

     

    Read though should not activate trigger, so only real cache inserts will cause DECO_NEW to be added.

     

    There are problem though, "Coherence has not confirmed insert to DB yet" doesn't mean what row is not inserted. Acknowledge process is asynchronous.

    So race condition is possible here.

     

    IMHO you can avoid race if you would implement BinaryEntryStore and check and put logic into erase() method to ignore entries in state 1.

    ReadWriteBackingMap is using internal synchronization to avoid races between update queue and removes.

     

    Regards,

    Alexey

  • 4. Re: Check if entry is persisted without check it on database
    jcpsantos Newbie
    Currently Being Moderated

    Hi Alexey,

     

    I think that with your info I've found out a solution for our problem.

    Let me know if there is any flaw in the following design:

     

    on entry created:

    • app adds DECO_new + coh adds DECO_store

     

    eventually coherence will store the entry and remove DECO_store, only DECO_new will remain

     

    on every next op in entry:

    • if (DECO_new and !DECO_store) - the entry was already stored by coherence, not new anymore
      • remove DECO_new

     

    on BinaryEntryStore:

    • store/storeAll
      • if (DECO_new): insert
      • else update
      • I think there may be a race condition here if the second update on the entry still sees DECO_store (the store operation may still be in progress) and as such does not remove DECO_new, the second store operation on the binary entry store will still see DECO_new and it is not an insert, but an update;
    • erase/eraseAll
      • if (DECO_new): ignore
      • else delete

     

    One of the problems in this design is that DECO_new is only removed when the entry is "touched" by our app (and we need to constantly check the DECOs on every operation on the entry), ideally, there should be a way to remove it as soon as coherence acknowledges the store in the database (when it removes DECO_store). Updating the DECOs in the BinaryEntryStore is not an option because cache update is best effort, there is no guarantee that it will be updated at all.

     

    Do you know of any other way to remove the DECO_new decoration?

     

    Thanks,

    João Santos

  • 5. Re: Check if entry is persisted without check it on database
    alexey.ragozin Explorer
    Currently Being Moderated

    See inline

    I think that with your info I've found out a solution for our problem.

    Let me know if there is any flaw in the following design:

     

    on entry created:

    • app adds DECO_new + coh adds DECO_store

    Decoration is a part of binary entry. You can add decoration only in entry processor or trigger (just to clarify)

     

    eventually coherence will store the entry and remove DECO_store, only DECO_new will remain

     

    on every next op in entry:

    • if (DECO_new and !DECO_store) - the entry was already stored by coherence, not new anymore
      • remove DECO_new

    Every update will erase all decoration, you should care about adding them (one more reason to put this logic into trigger, which can easily identify inserts)

     

    on BinaryEntryStore:

    • store/storeAll
      • if (DECO_new): insert
      • else update
      • I think there may be a race condition here if the second update on the entry still sees DECO_store (the store operation may still be in progress) and as such does not remove DECO_new, the second store operation on the binary entry store will still see DECO_new and it is not an insert, but an update;

    That is true, DECO_STORE is cleaned asynchronously. SQL offers you MERGE statement, though.

    • erase/eraseAll
      • if (DECO_new): ignore
      • else delete

     

    One of the problems in this design is that DECO_new is only removed when the entry is "touched" by our app (and we need to constantly check the DECOs on every operation on the entry), ideally, there should be a way to remove it as soon as coherence acknowledges the store in the database (when it removes DECO_store). Updating the DECOs in the BinaryEntryStore is not an option because cache update is best effort, there is no guarantee that it will be updated at all.

     

    Do you know of any other way to remove the DECO_new decoration?

    BinaryEntry cannot be update in BinaryEntryStore at all. Binary decorations are invisible, only place where you care about is BinaryEntryStore, which is called only once for each update. So, I do not understand why do you care about removing it at all.

     

    Thanks,

    João Santos

  • 6. Re: Check if entry is persisted without check it on database
    jcpsantos Newbie
    Currently Being Moderated

    Forgot to say, all our operations are done via EntryProcessors, hence, we always know when we are creating or updating an entry, and we are able to check and keep the decorations on the entry.

     

    We are using write-behind, not write-through, there may be several updates before the entry is stored to DB.

    Why do we want to keep the decoration on the entry after every update, and remove it as soon as it is stored to DB:

    • entry created through EP (deco_new set);
    • entry updated through EP (deco_new lost);
    • entry removed through EP (erase called in BinaryEntryStore, and we lost the decoration that would allow us not to delete the entry in DB since it is not there);

     

    This is why we need to keep the decoration between updates, we dont want to delete the entry from DB unless really needed. Therefore, we would like to remove it only then the entry is stored.

     

    If we do keep the deco_new until the entry is stored, why do we need to remove the decoration on the entry after it is stored in DB:

    • entry created through EP (deco_new set);
    • store called in BinaryEntryStore (deco_new kept, entry inserted to DB);
    • entry removed through EP (deco_new kept, erase called in BinaryEntryStore, and since we have the decoration signalling that it is a new entry, we will not delete it from the DB);

     

    This is why we would need to remove the deco_new decoration from the entry once it is stored in the DB, in this example we need to delete it from DB, but since the decoration is still there we will not be able to do so. This is why I was saying the following so that we can clean up deco_new:

    on every next op in entry:

    • if (DECO_new and !DECO_store) - the entry was already stored by coherence, not new anymore
      • remove DECO_new

     

    I'm doing some tests but I think that there is a race condition where this approach will not work. When we remove the entry through EP, we may still see deco_new and deco_store before calling entry.remove, so, we will keep deco_new on the entry to avoid deleting it in the binary entry store. The problem is that the store/storeAll operation may be in progress, and if we keep deco_new the entry wont be deleted from the database.

  • 7. Re: Check if entry is persisted without check it on database
    alexey.ragozin Explorer
    Currently Being Moderated

    You are totally right about race condition.

     

    I did some testing, looks like there is no reliable way to distinguish whenever entry was written or not if multiple updates is applied to it.

    In theory, by subclassing ReadWriteBackingMap you could introduce synchronization between store and erase, but I will have to rewrite handful of RWBM logic to plugin.

     

    There are another hole in this approach.

     

    What is entry does not exist in cache but present in database? You should do read through for each insert in cache, IMHO this will kill effect of this optimization.

     

    Regards,

    Alexey

  • 8. Re: Check if entry is persisted without check it on database
    jcpsantos Newbie
    Currently Being Moderated

    We will have to find another workaround to this issue, since the decorations do not offer a reliable way to distinguish entries stored from entries not stored, we cannot use them as we dont want to keep partial deleted entries on the database.

     

    Regarding the other hole you pointed, it would not be a problem:

    - we always know if the entry is being created or updated, and for both we use EntryProcessors;

    - if it is being created, inside the EP we just do what we need, dont call getValue and then set the entry value without loading the previous value of the entry;

    - if is being updated, read-through is done when we call getValue, but this is expected;

     

    The real optimization here would be not to delete these very "short lived entities" when not needed. It is like a producer-consumer problem where we use a cache do store values exchanged between them. If you're consumers are so fast that are able to consume the entries without these being stored into DB, then, it is a huge performance penalty for the consumers to perform a synchronous delete on DB of something that its not on DB. In fact, this will slow down consumers, causing more and more entries to start being stored in DB.

     


  • 9. Re: Check if entry is persisted without check it on database
    Jonathan.Knight Expert
    Currently Being Moderated

    Hi

     

    Just to correct something you said above...

    jcpsantos wrote:

    - if it is being created, inside the EP we just do what we need, dont call getValue and then set the entry value without loading the previous value of the entry;

    - if is being updated, read-through is done when we call getValue, but this is expected;

    read-thorugh is not done when you call getValue() Coherence will call load() on the CacheStore to load in an entry before it gets passed to your EntryProcessor. So if for some reason you were running a "Create" EntryProcessor then Coherence will call load() which will load the entry if the relevent data happened to be in the DB. It does not matter what your EntryProcessor does, load(0 will always have been called.

     

    JK

  • 10. Re: Check if entry is persisted without check it on database
    alexey.ragozin Explorer
    Currently Being Moderated

    Hi JK,

     

    I believe you are wrong.

    Read-though will not happen until you call getValue() in EP or aggregator. You can check isPresent() on entry and ignore it to avoid needles read-though.

    It is also possible is certain cases make a bulk read-though instead of iterating other all keys passed to EP in single thread, see Alexey Ragozin: Coherence 101, few things about read through you may want to know

     

    There were a case in my practice were checking isPresent() in EP to avoid needless read-though has reduced Database load by 30%.

     

    Regards,

    Alexey

Legend

  • Correct Answers - 10 points
  • Helpful Answers - 5 points