1 2 3 Previous Next 32 Replies Latest reply on Nov 15, 2006 10:52 AM by manik Go to original post
      • 15. Re: Hibernate/Cache conceptual mismatch
        manik

        Let's try and jot down what this method needs to perform. I'm calling it putFailFast() for now, but perhaps a different name (from 2.0.0) is better to avoid a mental conflict with the 1.x putFailFast() method which was a kludge.

        From this thread, I see that this method needs to:

        1) Suspend transactions so failures do not cause the tx to fail
        2) Do not attempt to acquite write locks if pessimistically locked. Ignore version mismatch exceptions if optimistically locked.
        3) 0 timeout on lock acquisitions
        4) Replication (or invalidation, if used) forced to be asynchronous.
        5) Exceptions suppressed.
        6) Warnings logged at a much lower level than usual.

        • 16. Re: Hibernate/Cache conceptual mismatch
          sebersole

          Perhaps something along the lines of "putOnReadFromExternal()"? Probably a bit long-winded, but it captures the idea perfectly I think (at least from the Hibernate use-case perspective). A more generic name might be "force()", as in "force this data into the cache".

          • 17. Re: Hibernate/Cache conceptual mismatch
            sebersole

            Regarding #3, what lock acquistions?

            Regarding #5, which exception conditions are you anticipating here that should get suppressed?

            • 18. Re: Hibernate/Cache conceptual mismatch
              manik

              #3: Read locks, at very least, so this does not conflict with an update(). Otherwise, the put() may overwrite an update().

              #5: To do with acquiring locks in 3, or replication exceptions to do with network issues.

              • 19. Re: Hibernate/Cache conceptual mismatch
                smarlow

                Regarding #1, if we suspend the active transaction at cache put time, wouldn't JBC send cache changes too early (before the suspended + later resumed tx completes?)

                • 20. Re: Hibernate/Cache conceptual mismatch
                  manik

                  Yes, but this is deemed acceptable since the cached versions are not deemed true representations of data (in this use case)

                  • 21. Re: Hibernate/Cache conceptual mismatch
                    otaylor

                    Manik: I think using a separate method is likely a cleaner approach. I do want to note
                    here that a separate method by itself can't solve the correctness issues I noted
                    in my comment of Sep. 18th, at least for the pessimistic case, since basically the
                    cache has no way of knowing whether the put() or the update() is providing newer
                    information. In the optimstic case with explicit versioning, the situation is better.

                    Scott: Are you wondering if we can get a "dirty read" if we call putFromExternalRead()
                    the transaction suspended? The assumption here is that the caller of
                    putFromExternalRead() only calls the method with data that was committed to the
                    database before the start of the outer transaction, and not with data that was updated
                    in the outer transaction. Hibernate, for example, makes that guarantee except in
                    the most exotic situations. (You might be able to fool it if you tried hard.)

                    • 22. Re: Hibernate/Cache conceptual mismatch
                      otaylor

                      Following up to my last comment: it may work pretty well to have "putFromExternalRead" simply never overwrite existing data.

                      • 23. Re: Hibernate/Cache conceptual mismatch
                        sebersole

                        Owen: (1) What is your deliniation of "put" and "update"? (2) I don't follow how a put could result in a dirty read...

                        Another possibility to consider is an "intention lock" where we temporarily lock a node for the duration of the read/putFromExternalRead cycle. This would guarentee two threads from attempting the same process. This would be instead of #2...

                        So what was the reason for forcing asynch replication? Why not synch? I did not follow where that came in at.

                        • 24. Re: Hibernate/Cache conceptual mismatch
                          sebersole

                          putFromExternalRead() should *always* over-write anything already there *unless the current data is write locked*. Although that write locked situation (afaict) actually indicates an exception condition.

                          • 25. Re: Hibernate/Cache conceptual mismatch
                            sebersole

                            Just to clarify my last comment. Keep in mind that putFromExternalRead() always results from the following usage pattern:

                            Object state = readFromCache();
                            if ( state == null ) {
                            state = readFromExternal();
                            putIntoCache( state );
                            }
                            ...

                            In Hibernate terms, readFromExternal is causing the data to get read from the database because it was not found in the cache. That db-read data is always the "truth" in a db-driven app...

                            The only way that data should not overwrite the current node data (putIntoCache) is if suddenly there has been a write lock applied to the node between readFromCache() and putIntoCache() being executed (which is the meaning of my "intention lock" comment).

                            • 26. Re: Hibernate/Cache conceptual mismatch
                              otaylor

                              When I've contrasted put() and update() I've been using the Hibernate cache terminology put() - cache fill (== putFromExternalRead()) - update - database change (== put()). I don't think a putFromExternalRead() would normally cause a "dirty read", but one possible interpretation of Scott's question was what would happen if you called putFromExternalRead() with data that wasn't yet committed to the database.

                              I don't know why the asynchronous replication of putFailFast() was added orginally, but my assumption is that it's about increasing concurrency and performance. Replicating cache fills synchronously doesn't increase correctness, so you might as well do it synchronously.

                              • 27. Re: Hibernate/Cache conceptual mismatch
                                manik

                                 

                                "otaylor" wrote:

                                I don't know why the asynchronous replication of putFailFast() was added orginally, but my assumption is that it's about increasing concurrency and performance. Replicating cache fills synchronously doesn't increase correctness, so you might as well do it synchronously.


                                Asynchronously, you mean (the last instance). Precisely. Using sync replication for this call doesn't buy you anything.

                                • 28. Re: Hibernate/Cache conceptual mismatch
                                  sebersole

                                  Regarding SYNCH/ASYNCH, consider the following in conjunction with my psuedo code, I am being concerned with the notion of an intention lock throughout the cluster. Consider:

                                  1) readFromCache()
                                  2) recv replication of data
                                  3) read from db (because #1 returned null)
                                  4) put into cache

                                  To me #2 needs to happen as early as possible in the process. Although perhaps I am being a bit pessimistic. Not sure; would need to think through it in more detail. Was more questioning why *that* decision was made as it seemed to not come from the previous discussions.

                                  • 29. Re: Hibernate/Cache conceptual mismatch
                                    otaylor

                                    "unless the current data is write locked" only works if you do have something like your Intention lock. (In my earlier post, I said "
                                    I'd argue that get() needs to establish a hard read lock (even when the node isn't there, even if the isolation mode is READ_COMMITTED) that is upgraded to a write lock on put() and then released/downgraded afterwards.", so yes, I agree that it is one possible solution)

                                    But I'd argue that replacing existing data on a putFromExternalRead() is never useful.

                                    a) I check the cache and find nothing there
                                    b) I read data from the database
                                    c) I go to write my data back to the cache and find something there already already

                                    Assuming that all database updates also cause cache updates, the data I find at step c) can't be older than the data I read at step b), so there is no point in replacing it.

                                    The only thing that I'm aware of that the intention lock does better than "don't replace" is handle the case of entity deletion. (it might also work better in the case where we are invalidating across the cluster rather than replicating- I haven't thought through that situation thoroughly)