Concurrency Control In Multi-Player Games Using Aerospike – @iamontheinet

  • Concurrency control is one of the main aspects of multi-player games where all the checks, conditional writes and game state updates must be made as fast as possible and with minimal client/server calls in order to keep the game fair and square.
  • This application uses the Aerospike Node.js Client to store and retrieve game data and AngularJS web framework to illustrate end-to-end application development in Aerospike DB.
  • In this application, concurrency control is achieved by putting conditional writes and game state updates on the server using User Defined Functions.
  • For every move (i.e. user selecting a square) all the client has to do is execute the UDF by passing in the game record key, current user’s username and the square he/she just clicked on.
  • The UDF then takes care of the rest — checking, setting, and updating the state of the game in a single-record transaction — where it always interacts with the most recent (game) record unlike other implementation where conditional writes and updates are coded in the client; where the client can potentially operate on outdated game record and wrongly overwrite true state of the game.

Concurrency control is one of the main aspects of multi-player games where all the checks, conditional writes and game state updates must be made as fast as possible and with minimal client/server calls in order to keep the game fair and square. This is especially critical in turn-based games where careless implementation (such as putting code that alters the game state in the client) can lead to concurrency related “race condition” from creeping in.

@iamontheinet: [Blog+code] Concurrency in multi-user apps using user-defined functions | #NoSQL #NodeJs…

Concurrency control is one of the main aspects of multi-player games where all the checks, conditional writes and game state updates must be made as fast as possible and with minimal client/server calls in order to keep the game fair and square. This is especially critical in turn-based games where careless implementation (such as putting code that alters the game state in the client) can lead to concurrency related “race condition” from creeping in.

For example, consider a tic-tac-toe game between John and Jane. If John played three moves simultaneously by opening different browser windows before Jane played her turn, sequence of updates would result in John winning the game by way of “cheating.” Good for John but not so much for Jane! (Till she figures out the same technique… yea, John!)

In this post we will look at a web-based tic-tac-toe game with multiple players playing against each other at the same time. This application uses the Aerospike Node.js Client to store and retrieve game data and AngularJS web framework to illustrate end-to-end application development in Aerospike DB.

In this application, concurrency control is achieved by putting conditional writes and game state updates on the server using User Defined Functions. UDFs are a powerful feature of Aerospike DB and they can be used to extend the capability of the Aerospike DB engine both in terms of functionality and performance. For more information on UDFs, click here. But wait, there’s more! Since the UDFs reside and execute on the server, the logic within it gets executed closer to the data with minimal client/server calls. Effectively providing much better performance in addition to concurrency control. BooYah!

Even though this is a pretty lightweight application, I’ve used different technologies to make it decent enough – visually & functionally – and covering all aspects as well as walking through the entire codebase is beyond the scope of this post. So, good understanding and working knowledge of the following technologies is presumed.

At a higher-level, here’s what happens — after creating an account and/or logging into an existing account, a user can:

NOTE: Users are notified of new game invites in real-time via Socket.io. Therefore, in this version of the application both users must be logged in to see the invites. In the future, I will enhance the app such that users will be able to see all pending invites as well as games they’ve already played. Stay tuned!

As the game progresses with every move, here’s what must happen in order to keep the game fair and square:

Before we get to the code, let’s examine the data model. This is important because data modeling is key to having a well performing application with data models at the core. Data models not only define how the data is structured and stored but sometimes they also tend to drive the UI and UX of the application.

In Aerospike DB, a Set (similar to tables in traditional RDBMs) is a collection of records, and each record is a collection of Bins (similar to columns in traditional RDBMs.) In this tic-tac-toe example, the application stores all game data in a Set called “games.” When a user initiates a new tic-tac-toe game by inviting another user to play, the application creates a new record in the “games” Set.

The “games” Set contains these Bins:

It’s time to look at some code. In Aerospike DB, UDFs are written in Lua. Lua is a powerful, fast, lightweight, embeddable scripting language. For more information on Lua, click here.

Below are the contents of UDF (/lib/udf/updateGame.lua) that checks, sets and updates state of the game in a single-record transaction manner. It accepts three parameters and returns a map with attributes status and message back to the client.

For every move (i.e. user selecting a square) all the client has to do is execute the UDF by passing in the game record key, current user’s username and the square he/she just clicked on. The UDF then takes care of the rest — checking, setting, and updating the state of the game in a single-record transaction — where it always interacts with the most recent (game) record unlike other implementation where conditional writes and updates are coded in the client; where the client can potentially operate on outdated game record and wrongly overwrite true state of the game.

And here’s how the UDF is registered and executed from the client application (code snippet taken from /lib/controllers/api.js):

Note: aerospikeDBParams is defined in /lib/controllers/aerospike_config.js

Concurrency Control In Multi-Player Games Using Aerospike – @iamontheinet

You might also like More from author

Comments are closed, but trackbacks and pingbacks are open.