Redis advancements – The use of list and application scenarios

Recently, I have been learning Redis intensively and writing while learning

Like it before you read it, make it a habit

First, the List type instructions

  • The list type is used to store multiple ordered strings, supporting 2^32 -1 elements.
  • Redis can insert (pubSH) and pop (pop) elements from both ends of a linked list, acting as queues or stacks
  • Supports reading sets of elements in a specified range
  • Reads the element with the specified subscript, etc
Notice that it's a linked list, not an array. This means that list inserts and deletes are very fast in O(1) time, but index positioning is slow in O(n) time, and when the last element of the list pops up, the data structure is automatically deleted and the memory is reclaimed.Copy the code

String: String;

In on the right and out on the left: queue

#Enter the queue
> rpush books python java golang
(integer) 3

#The queue length
> llen books
(integer) 3

#Remove the queue
> lpop books
"python"
> lpop books
"java"
> lpop books
"golang"
> lpop books
(nil)
Copy the code

In on the right and out on the right: stack

#Into the stack
> rpush books python java golang
(integer) 3

#Out of the stack
> rpop books
"golang"
> rpop books
"java"
> rpop books
"python"
> rpop books
(nil)
Copy the code

Slow operation

Lindex is equivalent to the Get (int Index) method of a Java linked list. It traverses the list, and performance deteriorates as index increases.

> rpush books python java golang
(integer) 3

> lindex books 1  # O (n) with caution
"java"

> lrange books 0 -1  Get all elements, O(n
1) "python"
2) "java"
3) "golang"


> ltrim books 1 0 This essentially clears out the list because the range length is negative
OK

> llen books
(integer) 0
Copy the code

Ltrim isn’t quite as literal as it sounds, it’s more like retaining it than removing it.

Since the ltrim arguments start_index and end_index define an interval in which values will be retained. This makes it ideal for implementing a fixed-length linked list

Iii. Usage Scenarios:The listUsed to doAsynchronous queue

The listCommonly used to doAsynchronous queueuse

  • Serialize (JSON) the task structure that needs to be deferred into a string in the Redis list

  • Another thread polls the data from the list for processing.

  • Lpush + LPOP = stack first out of the stack

  • Lpush + rPOP = queue FifO queue

  • Lpush + LTRIM = capped Collection

  • Lpush + BRPOP = Message Queue Message queue

The Redis queue is inescapableMessage lossThe problem

Message queues are typically implemented with a List:

  • The message is queued through the command LPUSH (BLPUSH)
  • Obtain messages by using the RPOP (BRPOP) command.

But the queue implemented this way is not secure. Because the RPOP (BRPOP) command features:

  • removeThe end-of-queue element (message) of the list is returned to the client. And then the elementThere are onlyIn the context of the client, the Redis serverThere is noThis element right here.
  • If the client is in the process of processing elementscollapseThat element is lost forever. This leads to:The client received the message successfully, but did not process it.

Try to resuscitate

So how do you implement a more secure queue? Try redis’s RPOPLPUSH (or its blocking version of BRPOPLPUSH) command.

The specific operations are as follows:

  • When an element is pushed (and deleted) from queue A, it is saved to queue B.
  • If the client handling the element crashes, it can still be found on queue B
redis> RPUSH mylist "one"
(integer) 1
redis> RPUSH mylist "two"
(integer) 2
redis> RPUSH mylist "three"
(integer) 3
redis> RPOPLPUSH mylist myotherlist
"three"
redis> LRANGE mylist 0 -1
1) "one"
2) "two"
redis> LRANGE myotherlist 0 -1
1) "three"
redis> 
Copy the code

There are two problems with this approach,

  • Multiple consumers simultaneously forward messages to the second queue, where (executed and unexecuted) messages pile up
  • Assuming your message is special and doesn’t repeat itself, you can passLrem A 0 "element"Function to find and delete the message and startup that specializes in processing the second queue client with the information in the queue number must be very small, if a client processing not to come over and cannot use concurrent, because using concurrent message pop out queue must be 2, if the pop out of the queue 2, then we would have to bypass the problem again.

The last

So try it out and find the RedisList

  • Do consumer confirmation ACK trouble
  • Can not repeat consumption, once consumption will be deleted
  • Queues are not reweighted

Therefore, it is recommended to use Redis 5 Stream or RocketMQ for queues in scenarios requiring high consistency. So far, I have not found that it is particularly suitable for redis list. Please leave a message at ❤️ if you think of it