← Back to team overview

launchpad-dev team mailing list archive

cassandra day 3

 

So, I didn't send a day two - it was primarily practical modelling
with the U1 team's needs.

Gary and I spent some time doing some modelling to get more to grips
with Cassandra and how things are done today.

We modelled sessions - trivial - and OOPS-tools.

The notation I'm going to use is this:
'foo' : the literal value foo.
foo: a variable representing foo
...: Repeated things.
+ prefixing a column name : 'has a secondary index'
(Thing) : this row is sorted on Thing. For instance
'Address':value(timestamp) - sorted on the timestamp.

ColumnFamily(aka Table): CF|SCF (ColumnFamily or SuperColumnFamily)

Row-Key :   [+]ColumnName:(value)

Remember too that every concrete column - essentially a stored cell -
has a timestamp on it.

e.g.

'Sessions':CF
UserId:   'Pickle':pickle
...

'SessionUse':CF
'Sessions': UserId:''(timestamp)

models our user session data: the column family is called 'Sessions',
the row key is the userid, there are two columns 'Pickle' and
'LastAccessed' which respectively have the pickled content and the
last date the session was accessed. We can garbage collect sessions by
reading the lowest rows from SessionUse['Sessions']. We can read a
session by reading 'Sessions'[user_id]('Pickle') and we can record
that one was used by writing '' to 'SessionUse'['Sessions'][user_id].

We could easily start splitting out our pickle into custom key:values
anytime we want with this model.

A more interesting example is oops-tools - if we wanted to, how would
we do that little app in Cassandra?

'Oopses':CF
# OOPS records
UUID:  'date':date, 'backtrace':backtrace, 'query_'N:query ...,
'params_'N:query_params ..., 'appserver':appserver_name,
'user_id':user_id,  'pageid':pageid, other key:value pairs as needed

'Queues':CF
# Things we background process - like determining the infestation for an oops.
'oopses': oops_id:''(timestamp)

'Infestations':CF
infestation_fingerprint: 'Bug':bug_id

'InfestationOopses':CF
infestation_fingerprint: oops_uuid:''(timestamp) ...

'InfestationCounts':SCF
infestation_fingerprint: date_range:[oops_exception_type:oops_count, ...]

'DateInfestations': CF
date_range: infestation_fingerprint: oops_count

Here we can see a work queue (the Queues CF), primary data store -
Oopses, our aggregation by fingerprint - infestation, mapping back
from infestation to the oopses and prepared statistics -
infestationcounts and dateinfestations.

I need to crash and sleep now, but I hope this provides something a
bit more concrete and relevant to what we do to chew on. This should
be able to implement our oops reports pretty efficiently with a couple
of background tasks: we could in principle insert directly into this
from the appservers (perhaps via rabbit for reliable delivery in the
presence of network glitches) and have near-instant access to the
data.

All in all I'm very glad Gary and I were here for the face time with
Matthew from Riptano - we're in a very good position now in terms of
understanding what it would take, and whether we'd want to, use
Cassandra in some capacity going forward.

For the million dollar question though - I think we probably want to
use Cassandra for some stub systems (e.g. oauth, sessions, oopses,
memcache replacement), as it has a much better scaling and schema
evolution story than postgresql - but the lack of transactions and
fundamentally different design approach needed mean that while
Cassandras performance and scaling are very attractive, we'd be nuts
to try and use hook it into Launchpad until our layering is sorted out
- we'd need a dedicated layer where we could abstract out the overall
operation vs the transaction/update logic.

I'm sure Gary will follow up with his perceptions - which I think are
not terribly different.

Gnight,
Rob



Follow ups