Serialize operations to the same key, handle async shutdown

## What does this do?

1. It pipes all operations in PersistentBlobCache through KeyedOperationQueue so that, for example, a Invalidate immediately before a Set can't ever Invalidate last and blow away the key.

2. It adds a new Observable to IBlobCache called `Shutdown`, which signals at the completion of Dispose. This means you can properly wait for the blob cache to shut down before exiting.