As you may remember from chapter 1, LISTs allow you to push and pop items from both ends of a sequence, fetch individual items, and perform a variety of other operations that are expected of lists. LISTs by themselves can be great for keeping a queue of work items, recently viewed articles, or favorite contacts.
In this section, we’ll talk about LISTs, which store an ordered sequence of STRING values. We’ll cover some of the most commonly used LIST manipulation commands for pushing and popping items from LISTs. After reading this section, you’ll know how to manipulate LISTs using the most common commands. We’ll start by looking at table 3.3, where you can see some of the most frequently used LIST commands.
|Command||Example use and description|
|RPUSH||RPUSH key-name value [value …] — Pushes the value(s) onto the right end of the list|
|LPUSH||LPUSH key-name value [value …] — Pushes the value(s) onto the left end of the list|
|RPOP||RPOP key-name — Removes and returns the rightmost item from the list|
|LPOP||LPOP key-name — Removes and returns the leftmost item from the list|
|LINDEX||LINDEX key-name offset — Returns the item at the given offset|
|LRANGE||LRANGE key-name start end — Returns the items in the list at the offsets from start to end, inclusive|
|LTRIM||LTRIM key-name start end — Trims the list to only include items at indices between start and end, inclusive|
The semantics of the LIST push commands shouldn’t be surprising, and neither should the pop commands. We covered a couple of these, along with both LINDEX and LRANGE, back in chapter 1. The next listing shows some uses of these push and pop commands.
The LTRIM command is new in this example, and we can combine it with LRANGE to give us something that functions much like an LPOP or RPOP call that returns and pops multiple items at once. We’ll talk more about how to make these kinds of composite commands atomic1 later in this chapter, as well as dive deeper into more advanced Redis-style transactions in chapter 4.
Among the LIST commands we didn’t introduce in chapter 1 are a few commands that allow you to move items from one list to another, and even block while waiting for other clients to add items to LISTs. Table 3.4 shows our blocking pop and item moving commands.
|Command||Example use and description|
|BLPOP||BLPOP key-name [key-name …] timeout — Pops the leftmost item from the first non-empty LIST, or waits the timeout in seconds for an item|
|BRPOP||BRPOP key-name [key-name …] timeout — Pops the rightmost item from the first non-empty LIST, or waits the timeout in seconds for an item|
|RPOPLPUSH||RPOPLPUSH source-key dest-key — Pops the rightmost item from the source and LPUSHes the item to the destination, also returning the item to the user|
|BRPOPLPUSH||BRPOPLPUSH source-key dest-key timeout — Pops the rightmost item from the source and LPUSHes the item to the destination, also returning the item to the user, and waiting up to the timeout if the source is empty|
This set of commands is particularly useful when we talk about queues in chapter 6. The following listing shows some examples of moving items around with BRPOPLPUSH and popping items from multiple lists with BLPOP.
The most common use case for using blocking pop commands as well as the pop/ push combination commands is in the development of messaging and task queues, which we’ll cover in chapter 6.
Exercise: Reducing memory use with LISTs
Back in sections 2.1 and 2.5, we used ZSETs to keep a listing of recently viewed items. Those recently viewed items included timestamps as scores to allow us to perform analytics during cleanup or after purchase. But including these timestamps takes space, and if timestamps aren’t necessary for our analytics, then using a ZSET just wastes space. Try to replace the use of ZSETs in update_token() with LISTs, while keeping the same semantics. Hint: If you find yourself stuck, you can skip ahead to section 6.1.1 for a push in the right direction.
One of the primary benefits of LISTs is that they can contain multiple string values, which can allow you to group data together. SETs offer a similar feature, but with the caveat that all items in a given SET are unique. Let’s look at how that changes what we can do with SETs.
1 In Redis, when we talk about a group of commands as being atomic, we mean that no other client can read or change data while we’re reading or changing that same data.