We’re hacking into the new year here at Hackers and Slackers, and in the process, we’ve received plenty of new gifts to play with. Nevermind how Santa manages to fit physically non-existent SaaS products under the Christmas tree. We ask for abstract enterprise software every year, and this time we happened to get a little red box.
If you've never personally used Redis, the name probably sounds familiar as you've been bombarded with obscure technology brand names in places like the Heroku marketplace, or your unacceptably nerdy Twitter account (I assure you, mine is worse). So what is Redis, you ask? Well, it's a NoSQL datasto- wait, where are you... NO! Don't leave! It's not like THAT, I swear!
What Redis is and When to Use It
Redis stores information in the familiar key/value pair format, but the term ‘NoSQL’ is more of a technicality than an indicator of use cases synonymous with NoSQL databases of the past. Redis looks the part for the very purpose it serves: a box that you fill with crap which may or may not be important down the line. It’s the perfect place to put a Starbucks gift card or the clothes you’ve already worn which aren’t quite ready to be washed yet.
All Users go to Heaven: Cloud Storage for User Sessions
Perhaps the most common use case is a glorified session cache. Similar to the way users might store temporary app information in cookies, Redis holds on to information which is fleeting. The difference is we now own this information inside our very own box, thus the Redis motto: “your box, your rules.”** I made this up: it holds zero truth.
Because temporary user information is in our hands as opposed to a fickle browser, we can decide just how temporary our “cache” is, having it persist across sessions or even devices. While local memory storage may as well be a place for throwaway information, and databases for persistent or eternal information, Redis is somewhere in between. As users interact and the information they create within our app evolves, we may choose at any point to promote information stored in Redis to a database, or perhaps have it stick around a little while longer. They’ll be thrilled to see their shopping cart still filled with the stupid things they almost bought while they were drunk yesterday.
When Variables are on a Bagel, You can Have Variables Any Time
In other words, Redis is great for solving the need of globally accessible variables throughout an entire application, on a per-user basis. Users who accidentally quit your app, move to a new context, or merely use your app for longer than your QA team are easier to manage when their temporary information is in a safe and global environment. Compare this to saving a user’s Pac-Man score to a global variable: the moment an app like Pac-Man crashes or restarts, that session is gone forever. Thus dies another three-letter app obscenity belonging to a leaderboard.
Speaking of Leaderboards...
Redis is great at counting in increments. This is probably made evident by the fact that it is a computer, and these are the things computers do. Something else that’s made great by counting: queues! Cues of tasks, notifications, chats, disappearing naked photos, etc: all of these things are ideally suited for our red box.
Getting a Red Box of Your Own
Playing around with a cloud-hosted Redis box will cost you maybe 5 bucks (monthly if you forget to cancel). Redis is open source so there are plenty of vendors to choose from with little differentiation between them. I’ll consider recommending whichever vendor offers to bribe me the most, but in the meantime I’ll leave the window shopping to you.
Setting up Redis should feel like setting up a cloud SQL database, except smaller and cuter. You’ll be able to pick adorable features for your box of possibly-but-not-surely-worthless stuff, such as hosted region, etc. Once you're set up you should have a host URL for reaching your instance:
Now we’re cooking with gas.
Using the redis-py Python Library
The main Python Redis library is typed as
redis, as in
pip install Redis. The easiest way to connect in any case is via a URI connection string, like such:
r = redis.Redis( url='rediss://:password@hostname:port/0')
Note the unique structure of the URI above:
- rediss://: precedes all Redis URIs; NOTE THE TRAILING COLON.
- password comes next, with the interesting choice to bypass usernames.
- hostname is the instance's URL... almost always a thinly veiled repurposed EC2 instance. That's right, we're being sold simple open source software hosted on AWS. Don't think about it.
- port is your preferred port of call after pillaging British trade ships. Just making sure you're still here.
- /database brings up the rear, which is the name of your database.
As with regular databases, other connection methods exist such as via SSL certificates, etc.
Storing and Getting Values
This is your bread and butter for interacting with Redis:
- .set(): Set a key/value pair by either overwriting or creating a new value
- .get(): Retrieve a value by naming the associated key
- hmget(): Accepts a variable number of keys, and will return values for each if they exist
- hmset(): Set multiple values to a single key.
- hgetall(): Get all values for a key where a key has been assigned multiple values.
It’s important to note that Redis by default returns bytes as opposed to strings. As a result, it is important to remember the encoding/decoding of values in order to retrieve them properly. For example:
# Setting a Value r.set('uri', str(app.config['SQLALCHEMY_DATABASE_URI']).encode('utf-8')) # Getting a Value r.get('uri').decode('utf-8')
If you happen to be remotely sane, you probably don't want to deal with encoding and decoding values over and again. Luckily we can ensure that responses are always decoded for us by setting the
decode_responses parameter to
True when setting up our Redis instance:
redis.StrictRedis(host="localhost", port=6379, charset="utf-8", decode_responses=True)
The redis-py documentation actually goes wayyy deeper than the 5 methods listed above. If you ever somehow manage to cover all of it, I have many questions about the type of person you are.
More Redis Libraries for Python
If the above encoding/decoding seems annoying, you aren’t the first. That’s why libraries like Redisworks exist. Redisworks allows for the seamless exchange of Python data types to and from Redis. Want to shove a Python dict down your box’s throat? Go ahead! You won’t even have to think about it very hard. There are plenty of similar libraries all aimed to make sad lives easier.
Want more? How about Asyncio’s very own asynchronous Redis library? Or how about the similar aioredis, another Asyncio Redis plug-in, which also includes pure Python parsing, clustering support, and things I don’t even understand! There are truly more Python libraries for Redis than you could need.
Finally, how could we ever forget Flask-Redis? We’ve already covered this, but is easily the first and last Redis library any Flask developer will use.
Your Box, Your Treasure, Your World™
Now that we’ve uncovered this niche between cached data and stored data, the possibilities are endless. The world is your oyster full of things which you may or may not choose to shove in your box.
Ok, fine. Perhaps this whole concept feels like a bit of an obscure niche hardly worthy of the words on this page. Just remember that feeling when the time comes that you too need a little red cube, and it will be waiting with love and compassion. A companion cube, if you will.