Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Axon: Lessons learned along the way

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →

Axon: Lessons learned along the way

This talk was about scaling Axon Framework at Casumo, and the lessons learned along the way.

Avatar for Josef Galea

Josef Galea

June 10, 2016

Other Decks in Programming

Transcript

  1. Event store • Most aggregates were stored in the same

    database for simplicity. • MySQL, by default, stores each table as a single file. • Event store eventually came up to about 1.5TB and was constantly growing as it had events related to wallet transactions. • It became cumbersome to handle a file that big and make backups etc.
  2. Archiving • ArchiveAwareEventStore, that can read events from a backing

    store if not found in main event store. • Archiving performed using a separate utility that creates snapshot and moves older events to a flat file with a memory mapped index file. • Flat file used for the simplicity of working with it. • Solution eventually scrapped due to some problems.
  3. Schema changes • We got in touch with Percona to

    help us design a better event store. • Use an auto increment ID. • Store aggregate identifier as binary. • Partition the table. • From the application, we started using aliases for event classes.
  4. Archiving II • Still using the ArchiveAwareEventStore. • Implemented within

    the application, triggered at specific intervals, or manually using JMX. • Creates snapshots, and exchanges partitions on MySQL. • Does not affect performance.
  5. Original wallet design Game Round Wallet Bonus Updater Bonus place

    bet withdraw publish events wallet events withdraw bonus part of bet publish events
  6. Scaling the application • Applications need to keep up (how

    eventual is your eventual consistency?) • One way to handle the increase in load is to scale the application horizontally. • Main requirement: all events coming from a particular player must be handled sequentially. • RabbitMQ makes it easy with its ordering guarantees.
  7. Different approaches • Use multiple consumers: there is no ordering

    guarantee. • Use an asynchronous cluster (@Asynchronous): queues are built in memory, and there is no "clean" shutdown. • Shard the queue on RabbitMQ itself. • Choose which consumers you want to shard from the code using @Partitioned.
  8. Scaling the IOPS • Having a lot of durable messages

    and queue puts a lot of strain on our SAN. • As load increases, an IOPS ceiling is reached that was affecting our response times. • Possible solutions: DisruptorCommandBus, infrastructural changes, or a home baked solution.
  9. New layout Main RabbitMQ instance Service specific RabbitMQ Service specific

    events shovelled towards main bus Other services’ events shovelled into service specific bus Service Service only publishes towards and reads from specific instance
  10. Replays • Replays are one of the selling point of

    event sourced systems. • This really depends on the size of the event store. • Fully asynchronous approach: read from one thread, apply events in another thread, persist in another thread. • Using blocking data structures while waiting for things to catch up severely affects performance. • Queue buildups may also cause system to go out of memory. • Apply back pressure.