Transactions are a common database requirement for when you need to make multiple insert or update operations together. That is, if one operation fails, you don't want to execute either operation; they must be completed together. In this article, we will learn how to use transaction in Redis with Python.
Let's take an example of caching orders in redis. In our applicaiton, we would like to store the user's purchase and increment the number of purchase they have. This is a good case for a transaction, because if the user purchase insert fails, we don't want the counter to increment.
For setting up Redis, I would recommend using a service for you in prod. Azure for example, has a great redis service that scales easily. However, you will want to learn redis and eventually how to scale it yourself. This will help with debugging cloud services or eventually, saving money and not using them.
We will start our intro to redis via using docker compose. Create a
docker-compose.yml file and add the following.
version: "3.2" services: redis: image: "redis:alpine" command: redis-server ports: - "6379:6379" volumes: - $PWD/redis-data:/var/lib/redis - $PWD/redis.conf:/usr/local/etc/redis/redis.conf environment: - REDIS_REPLICATION_MODE=master
Ensure you have docker installed and run
In python, the main used redis module is called
redis-py and can be installed using the follows.
pip install redis
Let's open up a new file,
index.py and add an transaction example.
We start by connecting to our redis instance.
import redis r = redis.Redis(host='localhost', port=6379, db=0)
By default, the pipeline interface wraps transactions, so to execute a transaction, we simply use the pipeline code. Let's start by creating a pipeline.
pipeline = r.pipeline()
Next, we can append our commands to this pipeline. Following from the example above, we want to add a user purchase and increment the count. Each of these commands will be appeneded to our pipeline and not sent. If one of the commands fails, neither will be executed.
pipeline.hset("user-purchase","customer", "keith") pipeline.hset("user-purchase", "amount", 100) pipeline.incr("customer-keith-purchase-count")
Finally, to send all commands, we can use the
exec function on the pipeline. Redis will execute all the commands and returns the results in an array.
pipeline.execute() print(results) // [0, 0, 1]
Below is the full code for context.
import redis r = redis.Redis(host='localhost', port=6379, db=0) pipeline = r.pipeline() pipeline.hset("user-purchase","customer", "keith") pipeline.hset("user-purchase", "amount", 100) pipeline.incr("customer-keith-purchase-count") results = pipeline.execute() print(results)
For future reference, if you would like to disable transactions, you can set the named parameter
pipeline = r.pipeline(transaction=False)