Caching and Scaling with Redis

Abhinav Sharma
9 min readJun 2, 2020

--

Cache? Heard of the term before? It happens to be a very crucial point when trying/ thinking to scale your system.

Let's suppose that you have a website that displays the stock prices for each available stock for each day. The stock prices get updated at each day's end. Whenever a user wants to see stock prices for the current day, the request hits your database and serves the user with corresponding days’ stock data.

Now Let's analyze the request load on the server for the same:-

Let the Total users = 1000000

A user requests the data = 3 times in a day.

Therefore the total number of requests in a single day =

1000000*3 = 3 million.

This means whenever the request comes you have to ask your database to serve the user with the same data, again and again, this basically means you are hitting your database 3 million times a day, and that too for the same data access every time. So why not store it somewhere such that it is served from the new location instead of hitting requesting your server again and again. Thus your server will get relieved of the load of 3 million requests each day for the same data. This is where caching comes into the picture.

Cache Memory

Storing your data in the cache memory temporarily and serving a million requests from the cache itself would eventually result in much more efficient and effective data serving and reduce the unnecessary load on your server.

Whats a Cache Memory?

Cache memory is a chip-based computer component that makes retrieving data from the computer’s memory more efficient. It acts as a temporary storage area that the computer’s processor can retrieve data from easily. But besides this is costlier too, so we can’t just keep on increasing the cache memory size unnecessarily.

How to design a caching system for your server?

Heard about Redis? NO? Don’t worry we will be diving inside it.

Redis (Remote Dictionary Server) is an in-memory data structure project implementing a distributed, in-memory key-value database with optional durability. Redis supports different kinds of abstract data structures, such as strings, lists, maps, sets, sorted sets, HyperLogLogs, bitmaps, streams, and spatial indexes. It's basically used as an in-memory caching system for fast distributed storage and retrieval of data. Besides its functionality is not just restricted as a caching system, it can be used as a database as well as a message broker (can read about message brokers from the given link, I will cover this in another blog of mine).

Soo this happens to be a simple bookish definition. Let's understand it now.

Storing and Retrieving Data From Redis Client:

When the user requests to store/access data there are basically 3 ways we can perform it, depending on your use case:

Write through CACHE:-

Write Through

So we have a Redis client where the user requests will fall on. As the user asks to store the data the Redis client requests the database with the same. Once the database responds with acknowledgment of successful storage of data then the data is stored in the cache and the acknowledgment is sent to the user. This flow is useful when there are a lot of re-reads then writes for the same data. But in case the number of writes is at par with the reads then it will be an inefficient approach as it takes two writes on two different systems which may result in low latency.

Write Around CACHE:-

Write Around

When the user asks to store the data, the data is first stored in the database. Then when an access data query comes it falls on the Redis client. In case of a miss, the client asks the database for the required data and stores in it and returns an acknowledgment to the user. Now for further access queries for the same data the data is servers from the cache.

This process is useful when the number of writes and re-reads are heavy. This ensures higher latency in data storage and retrieval but may fail in the case of a lot of data miss(i.e accessing different data at every request which is not already stored in the cache).

Write Back :-

Write Back

When the user asks to store the data, the data is first stored in the Redis client and the acknowledgment is returned to the user. Then asynchronously the data is stored in the database. This may result in higher efficiency for data storage and retrieval but may result in data loss, in case the cache layer dies.

Note:- The data storage and retrieval techniques can vary according to the requirements. Basically the combination of two or more is used in real-life scenarios.

Redis Clusters

Redis comes with Redis clusters which automatically shards data into multiple Redis nodes.

Whats Sharding?

Sharding basically means dividing a large set of data into multiple sets such that each set can independently represent a basic group of data. For example TINDER. It has users all around the globe , so if we are searching for users in INDIA(more specifically in Uttar Pradesh , and further to be more specific in Agra, then why to have a search query on the data of all the users? So in this case what we do is break the data into smaller parts like continents, we can further divide these parts into much smaller like countries and so on till cities, now when a user living in Agra whishes to see the users around him, then the query falls on the Agra / Uttar Pradesh Shard rather than the heafty data of all the users in the country / world. Thus increasing the efficency of the query and thereby increasing server performance.

Redis Cluster follows the same approach while storing data and further also provides some degree of availability during partitions, which is in practical terms the ability to continue the operations when some nodes fail or are not able to communicate. However, the cluster stops to operate in the event of larger failures (for example when the majority of masters are unavailable).

So in practical terms, what do you get with Redis Cluster?

  • The ability to automatically split your dataset among multiple nodes.
  • The ability to continue operations when a subset of the nodes are experiencing failures or are unable to communicate with the rest of the cluster.
Redis Master-Slave Architecture

Redis Master-Slave Architecture

Whats a master-slave architecture?

In a master-slave architecture, there is 1 master(more than 1 in real life) and N slaves for every master. All the read and writes are performed on the master itself. Subsequently, the slaves keep querying the master at specific time intervals, in case of new data availability and replicate the data. When the master is down the slaves chooses one among them as the new master and start serving the requests. Let's think of the master as the main database and the slaves as the clones of the main master database.

Let's suppose the master node having some important data failed as we talked of a possible case in case of a write-back cache storage technique. Therefore to overcome the data loss and in order to remain available in case of any master node failure, Redis Cluster uses a master-slave model where every hash slot has from 1 (the master itself) to N replicas (N-1 additional slaves nodes).

In our example cluster with nodes A, B, C, if node B fails the cluster is not able to continue since we no longer have a way to serve hash slots in the range 5501–11000.

However, when the cluster is created (or at a later time) we add a slave node to every master so that the final cluster is composed of A, B, C that is the master nodes, and A1, B1, C1 that are slaves nodes, the system is able to continue if node B fails.

Node B1 replicates B, and B fails, the cluster will promote node B1 as the new master and will continue to operate correctly.

However, note that if nodes B and B1 fail at the same time Redis Cluster is not able to continue to operate.

A hash value is calculated for every data and the data is stored in the particular Redis master, thus every data lies equally in every master, unlike stacking up on a single master thus increasing the load.

There are 16384 hash slots in a Redis Cluster with 3 master nodes, and to compute what is the hash slot of a given key, we simply take the CRC16 (16-bit Cyclic Redundancy Check Hash) of the key modulo 16384.

Data Consistency

Consistency Example

Redis Cluster is not able to guarantee strong consistency. But in practical scenarios, it is possible that Redis Cluster will lose writes that were acknowledged by the system to the client.

The first reason why Redis Cluster can lose writes is that it uses asynchronous replication. This means that during writes the following happens:

  • When the Redis client gets the requests it calculates the hash and writes it (to the master B for example).
  • The master B replies OK to your client and further starts an asynchronous write request to its corresponding salves B1, B2, B3.

Thus we can see that B doesn’t wait for the acknowledgment from B1, B2, B3 before replying to the client, since this would be a low latency penalty for Redis, so if your client writes something, B acknowledges the write but crashes before being able to send the write to its slaves, one of the slaves (that did not receive the write) can be promoted to master, losing the write forever.

This may be a very expensive loss in case of transaction data or other important data.

TCP Ports

TCP connection establishment process

Every Redis Cluster node requires two TCP connections open. The normal Redis TCP port used to serve clients, for example, 6379, plus the port obtained by adding 10000 to the data port, so 16379 in the example.

This second high port is used for the Cluster bus, which is used by nodes for failure detection. Clients should never try to communicate with the cluster bus port, but always with the normal Redis command port, however, make sure you open both ports in your firewall, otherwise, Redis cluster nodes will be not able to communicate.

The command port and cluster bus port offset is fixed and is always 10000.

Note that for a Redis Cluster to work properly you need, for each node:

  1. The normal client communication port (usually 6379) used to communicate with clients to be open to all the clients that need to reach the cluster, plus all the other cluster nodes (that use the client port for keys migrations).
  2. The cluster bus port (the client port + 10000) must be reachable from all the other cluster nodes.

This was a basic and brief description of what actually a cache is, why is it used, and the most popular Caching system, i.e REDIS, and it’s working.

CAN you think of building your own CACHING system now? With the basic functionalities at least? Stay tuned for the same in the next Blog.

If you liked it then please give a CLAP!!

Thank you… :)

--

--