Fernando DoglioMarch 29, 2022

Using Redis™* for Chat & Messaging

Technical articles and news about Memurai.

One key aspect of building a chat system is the need for adequate performance. You should not expect users to like your system if they feel like there is a delay between their message and the response of their counterpart if they suspect there may be system-generated delays in message transmission. This is why most platforms show you "<User's name> is typing..." kinds of messages to indicate that the delay is not on their part, but rather because of your friend’s slow fingers. Once you start designing a chat or messaging system, however, you start seeing a need for considerable back-and-forth of system-related data. Moreover, you must store that data to enable users, in case of disconnection, to adjourn a session and then to come back and pick up where they left off.

Therefore, when putting everything together, there will be two major systems at the core of your messaging platform:
- A speedy message delivery system.
- A very fast and reliable database, where you can not only store persistent data, but also access it sufficiently quickly.

Many solutions address one of these two requirements; therefore, mixing and matching can give you the basis of a core platform. However, there are other out-of-the-box solutions that can deal with both issues together with one simple install. The key to these systems is that, although they provide a very complex set of features, they do so through very simple and easy-to-use APIs (either directly or through multiple libraries for all major programming languages). Otherwise, the developer must deal with the complexity and the time-to-market for the application would suffer.

A speedy message delivery system

Speed is at the core of any messaging platform. Your data must travel from one person to the other (or potentially thousands) in a matter of milliseconds, which requires a reactive architecture. A reactive architecture is a way for your services to communicate with each other at the first chance they get, instead of having pre-set intervals between polling data from relevant data sources. This can be achieved by centralizing the data transfer via a messaging bus. A "Pub/Sub" mechanism enables a single client to send messages to multiple others without even knowing of their existence, let alone their location.

The above diagram illustrates the messaging bus helping Clients #1 and #2 communicate with other clients without having direct contact with them. Client applications must subscribe only once to be notified each time a new message arrives.

This is achieved through a very high-performance system that ensures that messages are delivered in under 10 ms on average to every client. Considering that the human reaction time averages around 250 ms, even when network latency and other external business logic that your platform might have is included, your users will be interacting with someone who could be sitting next to them.

Fast and reliable data access

The second key feature for a successful messaging system is data storage because not only do you have to send data quickly, you must also make sure the storage mechanism and access to it is fast enough. A traditional approach in this situation would be to rely on an SQL database. That would ensure that you have very well-defined structures for your users, messages, and chat rooms. However, while such an approach would work, a traditional RDBMS would add delay to your data operations by the very nature of its internal structure. A relational model implies that data becomes segregated across multiple structures. Once you need to make use of it, you must create complex queries to reintegrate it. The alternative No-SQL approach relies on in-memory data and is quite hard to beat performance-wise. The lack of schema and the straightforward data model greatly reduces the overhead of joining different tables and the memory I/O is orders of magnitude faster than the disk I/O that traditional RBDMSs tend to use. One solution is to use an in-memory cache and define a set of complex data types that can be used as values to further improve the way you deal with your platform's data. Redis is a product that addresses these issues while remaining easy to use. Its data types enable simple solutions to complex problems.

Use Redis Sets to store chat messages

Using the native deduplication logic of sets, you can ensure that your chat rooms are stored in memory without having to add extra code to avoid repeated messages.

Use Redis Sorted Lists to keep track of your received messages

A list of timestamp-sorted messages is a great way to store the most recent messages without implementing a sorting algorithm using your own logic.

Store user details using Redis Hashes

Hashes represent a key-value collection that allow you to store multiple properties together inside a single key. They are the perfect data type to store complex information such as user details.

Streams and Pub/Sub for accessing live data

Live messages received by clients can be transported by Redis' Pub/Sub mechanism as explained above. However, using Redis Streams, the system can offer even greater stability and performance by allowing out-of-the-box persistence for the queue and a more structured approach to accessing its content.

Based on the simple nature of a Redis application's messaging queue, the type of query you would be dealing with is very straightforward and would not require you to perform complex calculations. Most queries are just about retrieving data that has already been efficiently stored in memory. This brings the query response time to under 10 ms. Coupled with the fact that most operations are atomic, problems such as dealing with concurrent clients affecting your data are resolved by the platform itself. Your development team does not have to worry about dealing with concurrency or deadlocks.

The perfect system for a messaging platform

As a Windows-based alternative to the standard Redis, Memurai provides both options without having to worry about any of them individually. With a very straightforward installation on your systems, you will have achieved both main objectives:
- The need for fast-access data storage by having an in-memory cache with lightning-fast I/O.
- A stable message delivery system because of the incorporated Pub/Sub features.

In addition, you obtain a very developer-friendly product that provides a host of powerful features for developers to play with.

Memurai enables you to build a solution that is fully compatible with the Redis API, where any library for any supported programming environment will be compatible.

* Redis is a trademark of Redis Ltd. Any rights therein are reserved to Redis Ltd. Any use by Memurai is for referential purposes only and does not indicate any sponsorship, endorsement or affiliation between Redis and Memurai

Golden Gate Bridge