-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 
Author Message
 Post subject: VM wide Object caching, Thread Local requirements questions
PostPosted: Tue Mar 09, 2004 10:48 am 
Beginner
Beginner

Joined: Thu Feb 26, 2004 11:45 am
Posts: 46
I am aware that there have been many disccussions in the forum related to this area, and i've been through them. I'm sorry to add yet another, i hope it's not too redundant. I'm looking more for the approach/direction. I'll worry about code and implementation separately.

I've just begun using Hibernate. In terms of Mapping and support for my object domains, it appears that it will easily handle what i need. I'm thoroughly impressed with it's power and simplicity.

Okay, so now on to my caching and object sharing needs and requirements.

As I've said, i have been going through these forums and looking at all of the issues and solutions related to synchronized singletons, threadlocal variables, etc etc. I guess my problem is that it isn't clear to me in all of these cases, just what problem these solutions are designed to solve - since, of course everybody's requirements might be a bit different.

So i'd like to raise the question/requirements up a bit. At the risk of oversimplifying a possibly more complex question.


Application Environment:

Our application is Web/Servlet based using SOAP and any number of fat clients talking to it. As such any number of threads might be running. In fact, when we process a transaction (our transaction, not to be confused with Hibernate or DB), they are placed on a queue, picked up by workers processed and updated. Other threads may and do have a reference to our internal transaction and may, in fact, update an attribute or 2. They are notified when the transaction is completed, etc.


Problem/Question:
So my question is this. 2 threads have access to the same object. Perhaps one thread obtained it from a Hibernate session and passed a reference to it to another thread. Or, perhaps both threads obtained it independently, either might happen. (and this is hypothetical, i'm trying to determine whether there are even going to be 2 Hibernate Sessions here)

Now, either one of these threads may make changes to the object, or any child of it etc. Either one of these threads may then want to save it.

From what i can tell, this scenario will not do what i want without some help or specific usage patterns. Note, i haven't designed or written my DAOs yet. I am very flexible here, and i'm interested in getting going on it. I can say that the DAOs will "know" about our business objects - that is will not be generic. My only requirement is that the Business Objects are not aware of the DAOs - a common requirement.


Approaches I've read:

One common thread (pardon the pun) or restriction that i think i'm clear on is that a Hibernate Session is not threadsafe. That, of course, makes the solution to any problem a bit more challenging. However, handling this issue can be done a few different ways with totally different side effects. (i think)

Use Thread Local:

So, I see references to using ThreadLocal because Session is not threadsafe. I'm assuming that the actual Session is store in a ThreadLocal variable (i've seen this in some of the examples).

Cool, so unless i'm missing something, that solves a fundamental restriction that a Session is not thread safe. And by using ThreadLocal, you insure that each thread has it's own Session. Okay, that just ensures that the same session isn't used by 2 different threads at the same time. Each thread still can and probably does have it's own Session. Objects in 2 different sessions are still not in the same cache right? Therefore, objects referenced by 2 different threads are not as well? Or put it another way, if i load ObjectID=1 in Session1 and another thread does the same on Session2, we have 2 totally different objects in memory? If so, not good.

Synchronize Access to a Single VM Wide Session:
Another approach i'd seen had to do with Singleton pattern and sharing a session across the VM. Okay, fine - so whatever pattern we use here (i'm not interested in dissecting the many approaches), we are essentially synchronizing access to a session for all threads. Which means that only one "thing" is going on at any one time across all threads within a Session, depending on the length of the request.

Well, this too solves the thread safe issue by insuring that all threads are synchronized using the "same" Session. Both of these approaches solve the threadsafe problem, but seem to be entirely different approaches with respect to the application's potential requirements. It certainly will insure a single cache for all threads, but it scares the hell out of me with respect to performance. (should it? it does) Particularly when probably the majority of activity will NOT interfere because the objects will not be in common.

What are the general approaches to solve this stated requirement?
So, then - what (in general) are the alternatives here? I get the feeling that what i'm needing is to move to a/the second-level cache approach (which i need to read more about). But, before i go there, i'd like to know if my general understanding here is anywhere close - or am i missing something basic.

Another words - i want to insure that the answer to my question isn't. Silly, your problem is easy to solve - just do this!! Or, go figure out how to implement a VM wide second level cache.

Sorry for the long dissertation - didn't think it would be this long when i started out.

thanks for your indulgence.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 09, 2004 4:57 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 12:50 pm
Posts: 5130
Location: Melbourne, Australia
Quote:
2 threads have access to the same object.


Easy answer. Don't do this. Persistent objects are fundamentally non-threadsafe.

Quote:
Synchronize Access to a Single VM Wide Session


And don't do that either.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 09, 2004 5:46 pm 
Expert
Expert

Joined: Thu Jan 08, 2004 6:17 pm
Posts: 278
Like Gavin says, don't do that.

You say: "In fact, when we process a transaction (our transaction, not to be confused with Hibernate or DB), they are placed on a queue, picked up by workers processed and updated. Other threads may and do have a reference to our internal transaction and may, in fact, update an attribute or 2. They are notified when the transaction is completed, etc. "

*Why* do other threads have a reference to the internal transaction?

If I were you, I would arrange it so *all* you have is a queue of transactions and a pool of workers. Each worker is single-threaded. Each worker has its own Hibernate session. Each worker takes an application transaction off the queue and does EVERYTHING that needs to be done to handle the transaction.

If the worker wants to fire off some notification when it completes, great. But whoever picks up that notification does NOT also get a handle to the transaction object itself or to any persistent objects loaded by the worker; instead, the thread receiving the notification, if it needs to get hold of some persistent state, makes its *own* session and loads the necessary objects there.

The more concurrency you have, the more likely it is that multiple threads will be updating data that other threads will need, and the more you want to let the database handle the data concurrency issues. Don't worry about the object duplication; it's the stale data problems that should be concerning you more.

The bottom line question is, why do you think you need to have a single VM-level shared multithreaded cache of persistent objects? Do you KNOW you need it? What are the performance metrics that you know you will fail to meet if you don't have it? Or do you just *think* you need it? Have you done any benchmarks?

You can use the Hibernate second-level cache to optimize some amount of your trans-Session object loading, but you should (must!) still be using the one-and-only-one-thread-per-Session-and-per-group-of-Session-loaded-objects pattern.

Cheers,
Rob


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 09, 2004 6:43 pm 
Beginner
Beginner

Joined: Thu Feb 26, 2004 11:45 am
Posts: 46
Thanks for some input. Hmm, perhaps i'm in over my head conceptually.

Quote:
Why* do other threads have a reference to the internal transaction?

Maybe it's best answered with a scenario. Let's say a transaction that needs to be done for the sake of argument a "bank deposit". Sometimes we fire and wait, and other times we fire, and come back the next day to get the answer. The answer, for example, being the resulting balance (to keep it simple).

So we do, in fact, have a pool of workers that pull transactions off our internal queue and do what is necessary to "deposit" and enter the "balance". For those Servlets that fire and forget, there's no potential conflict.

For those servlets that fire and wait, they are sent a notification. When the notification is complete, the object is returned to the client. Yes, we could make changes to the application so that notification is sent, and the object is reloaded ... however this suggested solution works okay when, in fact, we "are" persisting. To make matters more interesting for us, we have some business objects that are purely transient, that a worker still needs to process, and return notification that the object has been updated (in memory). So, in this case, there is no place for the notified thread to "reload" a transaction from. It really "needs" to maintain a reference. well, i'll look into that solution, i suppose.


However, this is the simplest scenario. The suggestions that i'm getting are rather Hibernate/DB centric (as i would expect). In point of fact, workers processing the transaction are not necessarily the only objects in our application that might want to make a change to an object at some time or other. These workers are in place to process transactions, not necessarily to persist them (although maybe that is what you'r suggesting i add)

To make this more interesting, these transactions that we have are generally part of a collection of a larger "Batch" object. This 'Batch' object also is notified when all of it's transactions are complete so that it knows when "it's" complete. So i'm guessing that it will want to reload these transactions from a persistant store on notification as well?

This isn't hypothetical, the apps and business objects have been in place for over a year now.


Quote:
The bottom line question is, why do you think you need to have a single VM-level shared multithreaded cache of persistent objects? Do you KNOW you need it?


No i don't know that i need it, and hope i do not. I'm starting to get an understanding of the problem through your post. Thing is that our business objects may or may not be living in a "persistant" world, and when they are not, the only way to pass them around is by reference.

My other concern is that while it's all well in good to "say" that when an object is placed on a queue, insure that whoever placed it there get's a fresh copy and does not continue to use it's reference to it. I suppose i could document in capital letters somewhere that all objects that are placed on a queue should be dereferenced.

But other than never passing a reference to an object from one thread to another (gavin's suggestion), i don't know of any easy way to insure that any holders of a reference to this object get a fresh copy because it's just been persisted.

I suppose i could build in some sort of notification right into the business object.

okay, like i said, maybe i'm asking too much or am over my head. Or maybe i don't even have the problem i think i have.

Looks like i need to rescrew my head on and take a different view of this problem.

The notion that an object shouldn't be sitting on 2 different threads if it has the possibility of being persistant never ever occured to me. maybe it should have. Our current deployed archictecture fundamentally works on the notion that all transactions are placed in a queue and workers pick them up. Some times they are waited for, sometimes they are not. Sometimes they are persisted sometimes they are not. So keeping a reference to it is something i can't turn my back on...

i appreciate your indulgence and help. Looks like i got a lot more to analyze and/or prototyping to do.


oh, in terms of benchmarks. Reading in one of our transactions is really not that expensive. In the past, it appears that the round trip to Oracle took more time than anything else. Maybe it's the driver, i don't know. But if somebody is waiting on "one" transaction it doesn't take long. 300 milliseconds on average, most of which is wrapped in overhead.

On the other hand, when our customer is waiting to see a whole batch of say, only 300 transactions (a small one), well then we need to insure that we minimize round trips to oracle. Unfortunately our Batches, have Requests, which in turn have Transactions. I was able to optimize this in a previous home brew, but am hoping that hibernate will handle it okay. If not, i'm confident i can do something to help it.

thanks again


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 09, 2004 7:05 pm 
Expert
Expert

Joined: Thu Jan 08, 2004 6:17 pm
Posts: 278
Hibernate definitely gives you tons of ways to optimize your loading.

I guess one big thing I wonder about your current architecture is how do you handle failover and clustering? What if your server goes down (power failure / other disaster)? What happens to the state of your transient business objects?

We are also working on a transactional units-of-work job-processing notification-upon-completion sort of system. The main difference is we are starting with Hibernate as the foundation, so we are following the road of persisting *everything* -- every application transaction record, every completion flag, etc. We use JMS messages to handle completion notifications, but only AFTER we have updated the Hibernated job objects to mark them as "DONE". This is so if our whole cluster goes down we can still recover some kind of consistent system state just from the database alone (with all the standard database backup techniques to ensure we don't lose or corrupt our persistent state).

Cheers!
Rob


Top
 Profile  
 
 Post subject: Re: VM wide Object caching, Thread Local requirements questions
PostPosted: Fri Feb 11, 2011 5:41 pm 
Newbie

Joined: Fri Feb 11, 2011 5:35 pm
Posts: 5
Hi

I have been using transactions + concurrency control in my application. I tried using optimistic and pessimistic locking but it does not seem to work
I am using Spring and Hibernate 3.2.5.
My application scenario is :
1) user can select multiple number of files from the UI
2) for each file a NEW transaction is run consisting of SELECT and UPDATE

However, if I select 2 files for example, for processing, instead of:

SELECT
UPDATE
SELECT
UPDATE

the order of execution shows

SELECT
SELECT
UPDATE
UPDATE

the second transaction starts even before the first transaction finishes and reads the not yet updated values (dirty read).
I tried pessimistic locking with Query.setLockMode which does not seem to work with DB2 which is the database I am using. I also tried to set the hibernate.transaction.isolation values and also on the Spring side with isolation attribute for @Transactional annotation.

Can somebody please help me where am I going wrong/what additional needs to be done so that the second transaction starts only after the first finishes. Appreciate your help.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.