In class we have studied the concepts of strong and weak (eventual) consistency and strong and weak (optimistic) concurrency. Let's explore a few aspects of these concepts.
Answer: If an entry has no relationships with any others, then one can avoid any problems of concurrency by delaying the makePersistent() call until the object is completely instantiated. That way, it is not even in the cloud store until it is created as one (atomic) operation.
Answer: Since user actions are not reflected in queries immediately after the action, this is an eventual consistency situation.
One group pointed out (rightly) that the fact that something doesn't appear in search results immediately doesn't mean that twitter as a whole isn't strongly consistent, but just that twitter search isn't strongly consistent.
Answer: Consider the following schedule.
instance 1 | instance 2 |
setFirstName("Jon") | |
getFirstName() | |
getLastName() | |
setLastName("Smythe") |
Answer: The easiest solution is to surround the writes with a
begin()-commit()
block, as follows:
instance 1 | instance 2 |
begin() | |
setFirstName("Jon") | |
getFirstName() | |
getLastName() | |
setLastName("Smythe") | |
commit() |
To make the commit() throw an exception, consider:
instance 1 | instance 2 |
begin() | |
setFirstName("Jon") | |
setFirstName("Joan") | |
setLastName("Smythe") | |
commit() |
commit()
. Meanwhile, instance 2 has violated the transactional
integrity of the begin()-commit()
block, by changing the data
affected inside the block. Thus the commit() throws a (retryable) exception.
Note that one cannot force an exception to occur in a situation where
a begin()-commit()
block contains only reads, because
the writes are all that are committed!
In fact, this is exactly what the persistence factory does.
It marks what persistent data is used in the code between a
begin()
and a commit()
, and during the
commit()
, checks whether any of it has changed. If so,
the commit() fails. So, if another instance modifies something
persistent that is not referenced inside the begin()
to
commit()
code fragment, this does not cause the
commit()
to fail.
This is extremely clever, but it is possible to trick it. For example, suppose that I am in the commit block shown above to change first and last name, but inside that block, I read the salary for no particularly good reason. Then if another instance changes the salary during the commit block, the commit will fail, even though the salary change didn't affect the commit. The moral of this story is that the analysis done by the factory code is clever, but not extremely clever, and it can reject a commit for spurious reasons.