REDIS AS YOUR SWISS ARMY KNIFE

January 20, 2017
Contact Us
Weekly Shorts are topics we discuss in our weekly remote meeting related to recent work we have done with our customers
REDIS AS YOUR SWISS ARMY KNIFE

Most people think about Redis in terms of caching — they will use Redis as a cache engine when trying to squeeze more performance out of database-driven web application when they want to boost the speed of local calculations, save temporary sessions or cookies, and so on. Caching is often the first step in improving performance, and since Redis keeps all data in RAM, it is supremely useful as a caching layer.

However, caching is just a small portion of the services Redis offers. Redis was designed to be a more comprehensive data management solution. It serves as an in-memory data structure with a key-value data model, and it belongs to the NoSQL family.

“What people know but tend to forget is that Redis also has awesome data structures that can be applied to tons of practical uses,” says Yaron Wittenstein, Software Architect at Spot.IM. “Redis has many data structures. You can think about Redis as having Lego bricks that you can employ for tailoring your own abstractions.”

Spot.IM uses Redis as their primary database. The company enables website owners and publishers to turn their websites into social networks based on their own content. They provide the website users a real-time conversation system, usually in the comments section. Their clients include the Huffington Post, Time Inc., LittleThings, JPOST, Russia Today and more.

“Since we are working in a real-time environment we were looking for a database that can give us optimized results and be simple to use as we implement our product,” says Wittenstein. “My CTO, Ishay Green, was the one to pick it up a long time ago. We use RedisLabs’ product. RedisLabs is an Israeli company that offers SaaS services for Redis. Moreover, they’ve developed in-house (proprietary, not open-source) solutions for better cluster management and also what they call Redis-on-SSD that saves parts of the data on SSD disks, so at the end of the day, we can deal with more data overall. Another important point is that we were looking for a flexible database that we could bend to our needs. Redis’ unique data structures were the best match for us.”

Short time to market

Since their decision to use Redis as their primary database, Spot.IM currently has more than 80 production Redis instances. The CPU usage for each Redis instance is less than 0.3%. The busiest Redis handlers field about 20,000 requests per second. Spot.IM serves roughly 1.8 million web pages in terms of rendering conversations. “Thanks to Redis, we can develop many features way faster, which means shorter delivery time to market,” says Wittenstein.

Redis’ basic structures are quite similar to Ruby’s in terms of data bricks. While Ruby’s primary data bricks include String, Hash, Array, and Integers, Redis’ primary data bricks include Key-Value, Hash, List, Counters, and Set or Sorted Sets.

Over these basic Redis structures, Spot.IM built many in-house structures and abstractions. Their structure layer, for example, includes Redis Entity, Redis Lock, Redis Folder, Redis Token, Auto-complete, and so on. Redis Entity can be a comment on a web page, but it can also come in other forms. Redis Lock is used for specific matters, such as distributed locks. Redis Token holds all the credentials for authorization and authentication. The auto-complete feature gives the user recommendations on what to write, and so on. “Redis is very helpful for creating useful structures, and it helps us build simpler software in a shorter time,” says Wittenstein. So what does a Redis entity in Spot.IM look like? Here is a sample of code they implemented for a general entity — a comment:

“Let’s take for example the Redis-Entity structure I wrote,” says Wittenstein, “A conversation is a collection of comments. Each comment is, in fact, an entity and has its content, commenter_id, creation time, and more. Behind the scenes, all those fields are translated into a single key-value in Redis.”

This single key-value in Redis looks like this:

#gist:<link rel="stylesheet" href="https://assets-cdn.github.com/assets/gist-embed-87673c31a5b37b5e6556b63e1081ebbc.css"><div id=\"gist90397687\" class=\"gist\">\n <div class=\"gist-file\">\n <div class=\"gist-data\">\n <div class=\"js-gist-file-update-container js-task-list-container file-box\">\n <div id=\"file-redis01\" class=\"file\">\n \n\n <div itemprop=\"text\" class=\"blob-wrapper data type-text\">\n <table class=\"highlight tab-size js-file-line-container\" data-tab-size=\"8\">\n <tr>\n <td id=\"file-redis01-L1\" class=\"blob-num js-line-number\" data-line-number=\"1\"><\/td>\n <td id=\"file-redis01-LC1\" class=\"blob-code blob-code-inner js-file-line\">Comment_id => { “commenter_id”: “u_1”, “content”: “Hello” …. }<\/td>\n <\/tr>\n<\/table>\n\n\n <\/div>\n\n <\/div>\n<\/div>\n\n <\/div>\n <div class=\"gist-meta\">\n <a href=\"https://gist.github.com/seanroisentul/aed8914520ca9d9b65cf026429eb5649/raw/2bf8058a2a7dfdb4e2138a4096f717a8890632d1/Redis01\" style=\"float:right\">view raw<\/a>\n <a href=\"https://gist.github.com/seanroisentul/aed8914520ca9d9b65cf026429eb5649#file-redis01\">Redis01<\/a>\n hosted with ❤ by <a href=\"https://github.com\">GitHub<\/a>\n <\/div>\n <\/div>\n<\/div>\n

From that line, they can pull out all the necessary data they need in order to use it later, either in the conversation or for website query analysis, for example.

Real-time conversations

They also wrote another layer of abstractions over Redis. From a functional point of view, the concept of those abstractions is just like the concept of micro-services. “We use the abstractions we wrote over Redis as our micro-services for the real-time conversation,” says Wittenstein. “In a single conversation, you will have different Redis databases, like Authentication, Article Metadata, Users, Conversation, and so on.”

Here are some of the back-end databases:

Back-end databases

The User abstraction, for example, is created when a user enters the website for the first time, even though he didn’t register. This user will get a unique identifier. That allows unregistered users to write comments on web pages that work under the infrastructure of the Spot.IM product.

A sample of code for this abstraction looks like this:

Sample of code for this abstraction

“We can see in the code that user_name should be unique. You can’t have the same username in use more than once at the same time. This abstract also has functions that can add user_id, update username, etc.,” Wittenstein explains.

What does it take to render a real-time conversation in Spot.IM?

“We have more than 12 databases to fetch from. We have some token we get from the front-end user. We have a cookie, and we have to figure out whether it has permission, whether the token has expired or been revoked. We also need to fetch the comment_id, and then I need to actually fetch its content. Maybe I want some overall data about the conversation, like the total number of comments in the conversation or the number of unique users. Each message can be reported, each message may have up-votes and down-votes, each user may be online or offline. Every user has its own name, display name.

“If you use Redis efficiently, the performance is quite good, since if you simplify it, it’s a TCP connection talking straight to Redis. It takes us less 15 milliseconds to render a conversation. If we dig into the time analysis, we will see that more than 40% of the time is Ruby code, and we all know that Ruby is not the fastest language out there. We get this time even though we don’t have concurrency — we are doing the requests serially. That’s happened because the connection is straight with Redis, and I can pull from each database a few fields in one request, thanks to the Redis pipeline deployment mechanism.”

And it is not just time — the back end at Spot.IM is less than 120,000 lines of code, and around 50% of them are tests. They have almost 20 isolated deploy services (abstractions) and 100 internal gems. Wittenstein developed all of it himself in 10 months.

So the next time you are thinking about databases with excellent performance, think about Redis. “Redis is definitely one of the primary reasons we were able to get a short time-to-market with our product while being able to serve a very high-demand volume of traffic,” says Wittenstein, “you can simply think about it as your Swiss Army Knife.”

REDIS AS YOUR SWISS ARMY KNIFE
Daniela Kortin Shterenzon
Operation & Community Manager
Daniela runs the finance and operations at ProdOps; from making sure the company has smooth operations and logistics activities as less as possible to running marketing campaigns and organizing meetups and public events. You can trust her common sense in any decision she needs to make. Her strength in finding ways to minimize waste. She must have been an octopus in a previous life due to the many things she has to handle at once!