1. Overview:
In Redis, the List type is a linked list of strings sorted in insertion order. Like an ordinary linked list in a data structure, we can add new elements to its head (left) and tail (right). During insertion, if the key does not exist, Redis will create a new linked list for the key. In contrast, if all elements in the linked list are removed, the key will also be deleted from the database. The maximum number of elements that can be contained in a List is 4294967295.
From the efficiency perspective of element insertion and deletion, if we insert or delete elements at both ends of the linked list, this will be a very efficient operation. Even if millions of records have been stored in the linked list, this operation can Completed in constant time. However, it should be noted that if the element insertion or deletion operation is performed in the middle of the linked list, it will be very inefficient. I believe this is not difficult to understand for developers with a good data structure foundation.
2. Related command list:
Command prototype | Time complexity | Command description | Return value |
LPUSHkey value [value ...] | O(1) | Insert all the Values given in the parameters into the header of the List Value associated with the specified Key. If the Key does not exist, this command will create an empty linked list associated with the Key before inserting, and then insert the data from the head of the linked list. If the value of the key is not of linked list type, this command will return relevant error information. | The number of elements in the linked list after insertion. |
LPUSHX key value | O(1) | Only when the Key specified in the parameter exists, the command will be associated with it The head of the List Value is inserted into the Value given in the parameter, otherwise no operation will occur. | The number of elements in the linked list after insertion. |
LRANGE key start stop | O(S+N) | The S in the time complexity is the offset represented by the start parameter, N Represents the number of elements. The parameters start and end of this command are both 0-based. That is, 0 represents the first element at the head (leftmost) of the linked list. The value of start can also be a negative value, -1 will represent the last element in the linked list, that is, the tail element, -2 will represent the second to last and so on. When this command obtains elements, the elements at the start and end positions will also be taken out. If the value of start is greater than the number of elements in the linked list, an empty linked list will be returned. If the value of end is greater than the number of elements, this command obtains all remaining elements in the linked list starting from start (including start). | Returns a list of elements within the specified range. |
LPOPkey | O(1) | Return and pop up the first element in the linked list associated with the specified Key, that is, the head element. If the Key does not exist, return nil. | The element at the head of the linked list. |
LLENkey | O(1) | Returns the number of elements in the linked list associated with the specified Key. If the Key does not exist, returns 0. If the type of Value associated with the Key is not a linked list, relevant error information is returned. | The number of elements in the linked list |
LREMkey count value | O(N) | N in the time complexity means in the linked list The number of elements. In the linked list associated with the specified Key, delete the first count elements whose value is equal to value. If count is greater than 0, traverse from beginning to end and delete. If count is less than 0, traverse from end to beginning and delete. If count is equal to 0, delete all elements in the linked list that are equal to value. If the specified Key does not exist, 0 is returned directly. | Returns the number of deleted elements. |
LSETkey index value | O(N) | N in time complexity represents the number of elements in the linked list. But when setting the head or tail elements, the time complexity is O(1). Set the value of the specified position in the linked list to the new value, where 0 represents the first element, that is, the head element, and -1 represents the tail element. If the index value Index exceeds the number of elements in the linked list, this command will return relevant error information. | |
O(N) | N in time complexity means finding the element The number of elements that need to be traversed. For head or tail elements, its time complexity is O(1). This command will return the element at the specified position (index) in the linked list. The index is 0-based, which means the head element. If the index is -1, it means the tail element. If the Key is not associated with a linked list, this command will return relevant error information. | Return the requested element, or nil if the index is out of range. | |
O(N) | N represents the number of deleted elements. This command will only retain elements within the specified range, thus keeping the number of elements in the link relatively constant. The start and stop parameters are both 0-based, with 0 indicating the header element. Like other commands, start and stop can also be negative values, and -1 represents the tail element. If start is greater than the end of the linked list, or start is greater than stop, this command will not report an error, but will return an empty linked list, and the Key will also be deleted. If stop is greater than the number of elements, all elements remaining from start are retained. | ||
LINSERT key BEFORE|AFTER pivot value | O(N) | In time complexity, N represents the number of times that need to be traversed before finding the pivot of the element. Number of elements. This means that if the pivot is at the head or tail of the linked list, the time complexity of this command is O(1). The function of this command is to insert the element value in the parameter before or after the pivot element. If the Key does not exist, this command will do nothing. If the Value type associated with Key is not a linked list, related error information will be returned. | The number of elements in the linked list after successful insertion. If pivot is not found, -1 is returned. If key does not exist, 0 is returned. |
RPUSH key value [value ...] | O(1) | Insert parameters at the end of the List Value associated with the specified Key All Values given. If the Key does not exist, this command will create an empty linked list associated with the Key before inserting, and then insert the data from the end of the linked list. If the value of the key is not of linked list type, this command will return relevant error information. | The number of elements in the linked list after insertion |
RPUSHX key value | O(1) | Only when specified in the parameter Only when the Key exists, the command will insert the Value given in the parameter at the end of the associated List Value, otherwise no operation will occur. | The number of elements in the linked list after insertion. |
RPOPkey | O(1) | Return and pop up the last element in the linked list associated with the specified Key, that is, the tail element. If the Key does not exist, return nil. | The element at the end of the linked list. |
RPOPLPUSHsource destination | O(1) | Atomicly pop an element from the end of the linked list associated with the source key, and then pop the The element is inserted at the head of the linked list associated with the destination key. If the source key does not exist, the command will return nil and no other operations will be performed. If source and destination are the same key, it is equivalent to atomically moving the tail element in its associated linked list to the head of the linked list. | Returns popped and inserted elements. |
3. Command examples:
1. LPUSH/LPUSHX/LRANGE:
/> redis-cli #在Shell提示符下启动redis客户端工具。 redis 127.0.0.1:6379> del mykey (integer) 1 #mykey键并不存在,该命令会创建该键及与其关联的List,之后在将参数中的values从左到右依次插入。 redis 127.0.0.1:6379> lpush mykey a b c d (integer) 4 #取从位置0开始到位置2结束的3个元素。 redis 127.0.0.1:6379> lrange mykey 0 2 1) "d" 2) "c" 3) "b" #取链表中的全部元素,其中0表示第一个元素,-1表示最后一个元素。 redis 127.0.0.1:6379> lrange mykey 0 -1 1) "d" 2) "c" 3) "b" 4) "a" #mykey2键此时并不存在,因此该命令将不会进行任何操作,其返回值为0。 redis 127.0.0.1:6379> lpushx mykey2 e (integer) 0 #可以看到mykey2没有关联任何List Value。 redis 127.0.0.1:6379> lrange mykey2 0 -1 (empty list or set) #mykey键此时已经存在,所以该命令插入成功,并返回链表中当前元素的数量。 redis 127.0.0.1:6379> lpushx mykey e (integer) 5 #获取该键的List Value的头部元素。 redis 127.0.0.1:6379> lrange mykey 0 0 1) "e"
2. LPOP/LLEN:
redis 127.0.0.1:6379> lpush mykey a b c d (integer) 4 redis 127.0.0.1:6379> lpop mykey "d" redis 127.0.0.1:6379> lpop mykey "c" #在执行lpop命令两次后,链表头部的两个元素已经被弹出,此时链表中元素的数量是2 redis 127.0.0.1:6379> llen mykey (integer) 2
3. LREM/LSET/LINDEX/ LTRIM:
#为后面的示例准备测试数据。 redis 127.0.0.1:6379> lpush mykey a b c d a c (integer) 6 #从头部(left)向尾部(right)变量链表,删除2个值等于a的元素,返回值为实际删除的数量。 redis 127.0.0.1:6379> lrem mykey 2 a (integer) 2 #看出删除后链表中的全部元素。 redis 127.0.0.1:6379> lrange mykey 0 -1 1) "c" 2) "d" 3) "c" 4) "b" #获取索引值为1(头部的第二个元素)的元素值。 redis 127.0.0.1:6379> lindex mykey 1 "d" #将索引值为1(头部的第二个元素)的元素值设置为新值e。 redis 127.0.0.1:6379> lset mykey 1 e OK #查看是否设置成功。 redis 127.0.0.1:6379> lindex mykey 1 "e" #索引值6超过了链表中元素的数量,该命令返回nil。 redis 127.0.0.1:6379> lindex mykey 6 (nil) #设置的索引值6超过了链表中元素的数量,设置失败,该命令返回错误信息。 redis 127.0.0.1:6379> lset mykey 6 hh (error) ERR index out of range #仅保留索引值0到2之间的3个元素,注意第0个和第2个元素均被保留。 redis 127.0.0.1:6379> ltrim mykey 0 2 OK #查看trim后的结果。 redis 127.0.0.1:6379> lrange mykey 0 -1 1) "c" 2) "e" 3) "c"
4. LINSERT:
#删除该键便于后面的测试。 redis 127.0.0.1:6379> del mykey (integer) 1 #为后面的示例准备测试数据。 redis 127.0.0.1:6379> lpush mykey a b c d e (integer) 5 #在a的前面插入新元素a1。 redis 127.0.0.1:6379> linsert mykey before a a1 (integer) 6 #查看是否插入成功,从结果看已经插入。注意lindex的index值是0-based。 redis 127.0.0.1:6379> lindex mykey 0 "e" #在e的后面插入新元素e2,从返回结果看已经插入成功。 redis 127.0.0.1:6379> linsert mykey after e e2 (integer) 7 #再次查看是否插入成功。 redis 127.0.0.1:6379> lindex mykey 1 "e2" #在不存在的元素之前或之后插入新元素,该命令操作失败,并返回-1。 redis 127.0.0.1:6379> linsert mykey after k a (integer) -1 #为不存在的Key插入新元素,该命令操作失败,返回0。 redis 127.0.0.1:6379> linsert mykey1 after a a2 (integer) 0
#删除该键,以便于后面的测试。 redis 127.0.0.1:6379> del mykey (integer) 1 #从链表的尾部插入参数中给出的values,插入顺序是从左到右依次插入。 redis 127.0.0.1:6379> rpush mykey a b c d (integer) 4 #通过lrange的可以获悉rpush在插入多值时的插入顺序。 redis 127.0.0.1:6379> lrange mykey 0 -1 1) "a" 2) "b" 3) "c" 4) "d" #该键已经存在并且包含4个元素,rpushx命令将执行成功,并将元素e插入到链表的尾部。 redis 127.0.0.1:6379> rpushx mykey e (integer) 5 #通过lindex命令可以看出之前的rpushx命令确实执行成功,因为索引值为4的元素已经是新元素了。 redis 127.0.0.1:6379> lindex mykey 4 "e" #由于mykey2键并不存在,因此该命令不会插入数据,其返回值为0。 redis 127.0.0.1:6379> rpushx mykey2 e (integer) 0 #在执行rpoplpush命令前,先看一下mykey中链表的元素有哪些,注意他们的位置关系。 redis 127.0.0.1:6379> lrange mykey 0 -1 1) "a" 2) "b" 3) "c" 4) "d" 5) "e" #将mykey的尾部元素e弹出,同时再插入到mykey2的头部(原子性的完成这两步操作)。 redis 127.0.0.1:6379> rpoplpush mykey mykey2 "e" #通过lrange命令查看mykey在弹出尾部元素后的结果。 redis 127.0.0.1:6379> lrange mykey 0 -1 1) "a" 2) "b" 3) "c" 4) "d" #通过lrange命令查看mykey2在插入元素后的结果。 redis 127.0.0.1:6379> lrange mykey2 0 -1 1) "e" #将source和destination设为同一键,将mykey中的尾部元素移到其头部。 redis 127.0.0.1:6379> rpoplpush mykey mykey "d" #查看移动结果。 redis 127.0.0.1:6379> lrange mykey 0 -1 1) "d" 2) "a" 3) "b" 4) "c"
4. Tips on the linked list structure:
For the Value of the linked list structure, Redis provides some practical tips in its official documentation, such as the RPOPLPUSH command , a specific explanation is given below.
Redis linked lists are often used in message queue services to complete message exchanges between multiple programs. Assume that an application is performing an LPUSH operation to add new elements to the linked list. We usually call such a program a "Producer", while another application is performing an RPOP operation to remove elements from the linked list. We call this Such a program is called a "Consumer". If at this time, the consumer program crashes immediately after taking out the message element, because the message has been taken out and has not been processed normally, then we can think that the message has been lost, which may lead to the loss of business data or the loss of business status. Inconsistencies and other phenomena occur. However, by using the RPOPLPUSH command, the consumer program inserts the message into the backup queue after retrieving the message from the main message queue, and then deletes the message from the backup queue until the consumer program completes the normal processing logic. At the same time, we can also provide a daemon process. When a message in the backup queue is found to have expired, it can be put back into the main message queue so that other consumer programs can continue processing.
The above is the content of Redis Tutorial (3): List data type. For more related content, please pay attention to the PHP Chinese website (www.php.cn)!