Book Image

Instant Redis Optimization How-to

By : Arun Chinnachamy
Book Image

Instant Redis Optimization How-to

By: Arun Chinnachamy

Overview of this book

The database is the backbone of any application and Redis is a next generation NoSQL database which can provide ultra-fast performance if tuned and calibrated correctly. Instant Redis Optimization How-to will show you how to leverage Redis in your application for greater performance and scalability. Instant Redis Optimization How-to will show you how to make the most of Redis. Using real-world examples of Redis as a caching and queuing service, you will learn how to install and calibrate Redis to optimize memory usage, read and write speed, as well as bulk writes and transactions. If you want to use Redis for its blazing fast capabilities, then this book is for you.Instant Redis Optimization How-to shows you how to optimize and scale Redis with practical recipes on installation and calibration for performance and memory optimization as well as advanced features like PUB/SUB. This book starts by providing clear instructions on how to install and fine-tune Redis to work efficiently in your application stack. You will also learn how to maintain persistence, how to optimize Redis to handle different data types, as well as memory usage optimization. You will then learn how to use bulk writes and transactions, as well as publish/subscribe features to get the most out of Redis. Offering best practices and troubleshooting tips, this book will also show you how to manage and maintain performance. This book finishes by recommending the best client libraries for all major programming languages. By the end of this book you will know how to create blazing fast applications using Redis.
Table of Contents (7 chapters)

Using transactions and Pub/Sub (Advanced)


In this section, let us discuss about a couple of important and advanced concepts in Redis, transactions and Publish/Subscribe. Transaction makes a series of commands to be executed atomically. Publish/Subscribe, shortly known as Pub/Sub, helps in Inter-Process Communication (IPC) by decoupling the two processes using Redis as a shared data queue. Let us discuss both topics in detail and an example for a Publish/Subscribe queue.

Pub/Sub implements the messaging paradigm, which makes it easy to detach two processes. Instead of a process sending messages to receivers, the messages are published to a channel with no knowledge about the subscribers who use it. In the same way, subscribers can subscribe to any number of channels showing their interest, for the message has no knowledge about the publisher. Using the simple Pub/Sub service in Redis, we can achieve high scalability.

How to do it…

First, let us see how to use transactions in Redis followed by Publish/Subscribe.

Transactions

  1. The transaction is achieved using the MULTI/EXEC block.

  2. The client uses the MULTI command to initiate a transaction, followed by all the other commands. Any command sent after MULTI will return the string QUEUED.

  3. All the commands are queued and executed once the EXEC command is issued.

  4. In this case, MULTI just starts the command queuing and EXEC is responsible for executing the operations. We can exit the transaction by calling the DISCARD function, which will flush out all the commands in the transaction queue. Let us see an example of a transaction executed in redis-cli.

        redis> MULTI
        OK
        redis> SET key 10
        QUEUED
        redis> INCR key
        QUEUED
        redis> INCR key
        QUEUED
        redis>EXEC
        1. OK
        2. (integer) 11
        3. (integer) 12
    

Publish/Subscribe

  1. A process subscribes to any channel in Redis using the SUBSCRIBE command.

  2. Another process can publish a message to the mentioned channel in Redis using the PUBLISH command.

  3. The first process receives the published message from Redis and is free to process the message the way it wants.

  4. At any point of time, the process can unsubscribe from a channel using the UNSUBSCRIBE command.

How it works...

Every command in Redis is atomic in nature and a transaction makes a series of commands to be executed atomically. All the commands are executed serially. As Redis is single-threaded and can process only one request at a time, it is not possible for commands issued by another client to be executed while a transaction is under execution. This provides the required isolation.

Transactions might sound familiar to pipelining, even those in which the commands are queued. But the difference is that the queue is maintained at the server for transactions, while pipelining is by clients.

The Pub/Sub feature does not involve any key/value storage but lets Redis act as a broadcast server that connects between the publishers and subscribers in real time. This makes Redis a good fit to implement modern web applications, such as chatting systems, messaging platforms, and notification systems.

There's more...

Let us discuss an example of how to use the Publish/Subscribe functionality in Redis.

A Publish/Subscribe example

Let us take the example where we are trying to implement a notification system in which we show a notification on receiving a new e-mail, on receiving a chat message, and if someone adds you as a friend. We have three processes working on these three functionalities. Our notification system needs to subscribe to all the three channels and show notifications.

To subscribe to a particular channel, the SUBSCRIBE command should be used if we know the channel name. In this case, our notification client will issue a subscription to all three channels.

SUBSCRIBE email chat addfriend

Note

If you want to subscribe to all channels matching a pattern, use PSUBSCRIBE instead. Find more information at http://redis.io/topics/pubsub.

Once subscribed to any channel, the client cannot issue any other commands but has to wait and read the stream of messages coming back from the server. There are three types of messages possible, which are identified by the first element of the message:

  • SUBSCRIBE: This message is sent by the server to the clients to confirm the subscription, along with the total number of channels we have subscribed to.

  • UNSUBSCRIBE: This message is to acknowledge the successful unsubscription from the server. This also contains the total number of channels we have active subscription to, as a third parameter.

  • MESSAGE: This is the actual message published by the other clients. The second parameter has the channel name and the third parameter is the actual message.

For our command, the response will look something like this:

SUBSCRIBE email chat addfriend
*3
$9
subscribe
$5
first
:1
*3
$9
subscribe
$4
chat
:2
*3
$9
subscribe
$9
addfriend
:3

The format is the same as the Redis protocol, where the first line defines the number of arguments, followed by the number of bytes in arguments, and then the data itself. This confirms our subscription to all three channels. If we publish a message to any of the channels from another redis-cli, we use the PUBLISH command in the following manner:

PUBLISH chat Hi

Our notification client will receive the message stream as follows:

*3
$7
message
$4
chat
$2
Hi

Let us consider a case in which we want to give a provision to the user to stop notifications for chats when busy. In this case, it is possible to unsubscribe from a specific channel by using the UNSUBSCRIBE command.

UNSUBSCRIBE chat
*3
$11
unsubscribe
$4
chat
:2

The reply from the server will confirm the unsubscription, and also mentions that we have two remaining active subscriptions. Due to the simplicity of the Publish/Subscribe functionality, it is very easy to implement.

Caveats in transaction

Redis does not support rollbacks, which is an odd behavior when compared to other relational databases. So, even when an error occurs, Redis continues to execute the other commands. The rollbacking ability was sacrificed to keep the internal design simple and to keep Redis running fast. Another reason for not supporting rollbacks is that errors in Redis commands are only possible because of programming errors.

But there is a caveat. Due to the sequential manner of Redis's command execution in a transaction, it is not possible to perform a read operation during the transaction. Let us consider a case in which we want to write data into Redis based on the value in another key.

    val = GET key1
    MULTI
    if val > 20:
        SET key2 (val+1)
    EXEC

In this case, let us assume the value in key1 was changed (value more than 20) after we read it and before the EXEC was executed. We will end up setting a wrong value to key2. Redis supports Check and Set (CAS) transactions to mitigate this issue. To use CAS, we need to use the WATCH command. The WATCH command provides a form of locking called Optimistic Locking, which is powerful.

    WATCH key1
    val = GET key1
    MULTI
    if val > 20:
        SET key2 (val+1)
    EXEC

In this case, if the value of key1 changes after the WATCH statement and before the EXEC command is executed, the transaction will fail. The client needs to retry again. The WATCH command can be called multiple times to watch multiple keys, or WATCH is called with multiple keys. The WATCH list is cleared once EXEC or UNWATCH is called.

Tip

You can combine transactions with pipelining to perform faster atomic operations.