I'm originally familiar with relational-style data stores. I'm currently looking into NoSQL and trying to learn about its use-cases. Here's something that's been bugging me lately.
How do you do the following operation using the typical NoSQL product?
- reads multiple inputs
- computes new values for them (each output depends on ALL inputs)
- writes the values back
An example of this, from past experience with other issues, is as follows. You have a web game with various user accounts. Users can initiate attacks on each other, where the attack formula is complicated black-box game-logic which determines the mutual outcome based on both inputs and randomness. You need to enforce that an attack happens atomically, and that the inputs reflect a consistent point in time, as do the outputs, with regard to some serialization of the sequence of attacks performed in the game.
It's important that:
- all outputs depend on all inputs in some complex way we can't break apart (i.e. we can't just convert this to the textbook bank accounts to transaction ledgers example, we can't use only write-ahead logging, etc)
- in other words, we aren't doing P1 += $10, P2 -= $10
- more like, we're [for the sake of argument] doing [essentially something as complex/irreducible as] (P1, P2) = (sha1(P1+P2), sha1(P1-P2)) where we want a consistent snapshot of the values of P1 and P2 [not to say that particular line is a good example for an actual game]
- the inputs will be an arbitrary choice of small subset of records, so we can't just used a compound record
- an external observer sees a uniform/consistent state either before or after ALL the operations but not in between
My particular example was an issue we encountered. We were actually using a relational database, but we were not using its transactional features like we should have. As a result, online players attacking each other repeatedly tended to generate incorrect results and generate phantom resources for both attackers.
In the relational model, I would have done this using a transaction. Come to think of it, this may be a textbook example of transactions.
How would I go about achieving this in NoSQL?
Here are answers I have seen on SO and elsewhere which I consider a bad fit for this particular instance:
- ignore the possibility of race conditions
- redesign the game so that this isn't an issue
- manually implement 2PC, bakery algorithm, etc. using the data store
- use an external locking service
... although if you believe any or all of them is a good solution, please let me know how and why.
I would appreciate some pointers on how to implement this sort of thing in practice.
Thanks!