1. 개요:
Redis에서 List 유형은 삽입 순서로 정렬된 문자열의 연결 목록입니다. 데이터 구조의 일반적인 연결 목록과 마찬가지로 머리(왼쪽)와 꼬리(오른쪽)에 새 요소를 추가할 수 있습니다. 삽입하는 동안 키가 존재하지 않으면 Redis는 해당 키에 대한 새 연결 목록을 생성합니다. 반대로 연결된 목록의 모든 요소가 제거되면 해당 키도 데이터베이스에서 삭제됩니다. 목록에 포함될 수 있는 최대 요소 수는 4294967295입니다.
요소 삽입 및 삭제의 효율성 측면에서 연결 목록의 양쪽 끝에 요소를 삽입하거나 삭제하면 연결 목록에 수백만 개의 레코드가 저장되어 있어도 매우 효율적인 작업이 됩니다. 일정한 시간 내에 완료될 수 있습니다. 그러나 연결리스트 중간에 요소 삽입이나 삭제 작업을 수행하게 되면 매우 비효율적이라는 점에 유의해야 한다. 좋은 데이터 구조 기반을 갖춘 개발자에게는 이것이 이해하기 어렵지 않다고 생각합니다.
2. 관련 명령어 목록:
명령 프로토타입 | 시간 복잡도 | 명령 설명 | 반환 값 |
LPUSHkey 값 [value ...] | O(1) | 지정된 Key와 관련된 List Value의 헤드에 매개변수에 제공된 모든 값을 삽입합니다. 키가 존재하지 않는 경우 이 명령은 삽입하기 전에 키와 연결된 빈 연결 목록을 만든 다음 연결 목록의 헤드에서 데이터를 삽입합니다. 키 값이 연결 목록 유형이 아닌 경우 이 명령은 관련 오류 정보를 반환합니다. | 삽입 후 연결 리스트의 요소 수입니다. |
LPUSHX 키 값 | O(1) | 파라미터에 지정된 Key가 존재하는 경우에만 해당 Key와 명령어가 연결됩니다. 매개변수에 지정된 값에 목록 값이 삽입됩니다. 그렇지 않으면 작업이 발생하지 않습니다. | 삽입 후 연결 리스트의 요소 수입니다. |
LRANGE 키 시작 중지 | O(S+N) | 시간 복잡도에서 S는 시작 매개변수로 표시되는 오프셋, N을 나타냅니다. 요소의 수. 이 명령의 시작 및 끝 매개변수는 모두 0부터 시작합니다. 즉, 0은 연결된 목록의 첫 번째 요소(가장 왼쪽)를 나타냅니다. start 값은 음수일 수도 있습니다. -1은 연결된 목록의 마지막 요소, 즉 꼬리 요소를 나타내고, -2는 끝에서 두 번째 요소를 나타내는 식입니다. 이 명령으로 요소를 얻을 때 시작 위치와 끝 위치의 요소도 제거됩니다. start 값이 연결 목록의 요소 수보다 크면 빈 연결 목록이 반환됩니다. end 값이 요소 수보다 큰 경우 이 명령은 start(start 포함)부터 시작하여 연결된 목록의 나머지 모든 요소를 가져옵니다. | 지정된 범위 내의 요소 목록을 반환합니다. |
LPOPkey | O(1) | 지정된 키와 연결된 연결 목록의 첫 번째 요소, 즉 머리 요소. 키가 존재하지 않으면 nil을 반환합니다. | 연결리스트의 선두에 있는 요소. |
LLENkey | O(1) | 지정된 키가 없는 경우 연결된 목록의 요소 수를 반환합니다. , 0이 반환됩니다. Key와 연관된 Value의 유형이 연결리스트가 아닌 경우 해당 오류 정보를 반환합니다. | 링크드 리스트의 요소 개수 |
LREM 키 카운트 값 | O(N) | 시간복잡도에서 N 연결된 목록에서 요소의 수를 의미합니다. 지정된 Key와 연결된 연결 목록에서 값이 value와 동일한 첫 번째 count 요소를 삭제합니다. count가 0보다 크면 처음부터 끝까지 순회하고 삭제합니다. count가 0보다 작으면 끝에서 처음으로 순회하여 삭제합니다. count가 0이면 연결리스트에서 value와 같은 모든 요소를 삭제합니다. 지정된 키가 존재하지 않으면 0이 직접 반환됩니다. | 삭제된 요소의 수를 반환합니다. |
LSET 키 인덱스 값 | O(N) | N은 시간 복잡도로 연결 리스트의 요소 수를 나타냅니다. 그러나 머리 또는 꼬리 요소를 설정할 때 시간 복잡도는 O(1)입니다. 연결된 목록에서 지정된 위치의 값을 새 값으로 설정합니다. 여기서 0은 첫 번째 요소, 즉 머리 요소를 나타내고 -1은 꼬리 요소를 나타냅니다. 인덱스 값 Index가 연결된 목록의 요소 수를 초과하는 경우 이 명령은 관련 오류 정보를 반환합니다. | |
LINDEX 키 인덱스 | O(N) | N은 시간 복잡도에서 요소를 찾는 것을 의미합니다. 통과해야 하는 요소의 수입니다. 머리 또는 꼬리 요소의 경우 시간 복잡도는 O(1)입니다. 이 명령은 연결된 목록의 지정된 위치(색인)에 있는 요소를 반환합니다. 인덱스는 0부터 시작하며, 인덱스가 -1이면 꼬리 요소를 의미합니다. 키가 연결 목록과 연결되어 있지 않으면 이 명령은 관련 오류 정보를 반환합니다. | 요청된 요소를 반환하거나, 인덱스가 범위를 벗어나면 nil을 반환합니다. |
LTRIM키 시작 중지 | O(N) | N은 삭제된 요소 수를 나타냅니다. 이 명령은 지정된 범위 내의 요소만 유지하므로 링크의 요소 수는 상대적으로 일정하게 유지됩니다. 시작 및 중지 매개변수는 모두 0을 기반으로 하며 0은 헤더 요소를 나타냅니다. 다른 명령과 마찬가지로 start 및 stop도 음수 값일 수 있으며 -1은 꼬리 요소를 나타냅니다. 시작이 연결된 목록의 끝보다 크거나 시작이 중지보다 큰 경우 이 명령은 오류를 보고하지 않지만 빈 연결 목록을 반환하며 동시에 키가 삭제됩니다. 중지가 요소 수보다 크면 시작부터 나머지 모든 요소가 유지됩니다. | |
LINSERT 키 BEFORE|AFTER 피벗 값 | O(N) | 시간 복잡도에서 N은 이동해야 하는 횟수를 나타냅니다. 요소 피벗을 찾기 전 요소 수입니다. 즉, 피벗이 연결 목록의 머리 또는 꼬리에 있는 경우 이 명령의 시간 복잡도는 O(1)입니다. 이 명령의 기능은 피벗 요소 앞이나 뒤에 매개변수에 요소 값을 삽입하는 것입니다. 키가 존재하지 않으면 이 명령은 아무 작업도 수행하지 않습니다. Key와 연관된 Value 유형이 연결 목록이 아닌 경우 관련 오류 정보가 반환됩니다. | 삽입 성공 후 연결된 목록의 요소 수입니다. 피벗을 찾을 수 없으면 -1이 반환됩니다. 키가 없으면 0이 반환됩니다. |
RPUSH 키 값 [값 ...] | O(1) | 지정된 값과 연결된 목록 값 끝에 매개변수를 삽입합니다. 주요 모든 값이 제공됩니다. 키가 존재하지 않는 경우 이 명령은 삽입하기 전에 키와 연결된 빈 연결 목록을 만든 다음 연결 목록의 끝에서 데이터를 삽입합니다. 키 값이 연결 목록 유형이 아닌 경우 이 명령은 관련 오류 정보를 반환합니다. | 삽입 후 연결리스트의 요소 개수 |
RPUSHX 키 값 | O(1) | 지정된 경우에만 매개변수에 키가 존재하는 경우에만 명령은 매개변수에 지정된 값을 연관된 목록 값 끝에 삽입합니다. 그렇지 않으면 작업이 발생하지 않습니다. | 삽입 후 연결 리스트의 요소 수입니다. |
RPOPkey | O(1) | 지정된 키와 연결된 연결 목록의 마지막 요소를 반환하고 팝업합니다. 꼬리 요소. 키가 존재하지 않으면 nil을 반환합니다. | 연결리스트 끝에 있는 요소입니다. |
RPOPLPUSH 소스 대상 | O(1) | 소스 키와 연결된 연결 목록의 끝에서 요소를 원자적으로 팝한 다음 pop the 요소는 대상 키와 연관된 연결 목록의 선두에 삽입됩니다. 소스 키가 없으면 명령은 nil을 반환하고 다른 작업은 수행되지 않습니다. 소스와 대상이 동일한 키인 경우 연결된 목록의 꼬리 요소를 연결 목록의 헤드로 원자적으로 이동하는 것과 같습니다. | 팝된 요소와 삽입된 요소를 반환합니다. |
3. 명령 예:
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. 연결 목록 구조에 대한 팁:
연결 목록 구조의 값에 대해서는 Redis에서 공식 문서에는 RPOPLPUSH 명령과 같은 몇 가지 실용적인 팁이 제공되며 구체적인 설명은 아래에 나와 있습니다.
Redis 연결 목록은 여러 프로그램 간의 메시지 교환을 완료하기 위해 메시지 대기열 서비스에서 자주 사용됩니다. 응용 프로그램이 연결 목록에 새 요소를 추가하기 위해 LPUSH 작업을 수행한다고 가정합니다. 우리는 일반적으로 이러한 프로그램을 "생산자"라고 부르고, 다른 응용 프로그램은 연결 목록에서 요소를 제거하기 위해 RPOP 작업을 수행한다고 가정합니다. 프로그램을 "소비자"라고 합니다. 이때 메시지 요소를 꺼낸 후 바로 소비자 프로그램이 충돌하는 경우, 메시지가 제거되어 정상적으로 처리되지 않았기 때문에 메시지가 손실된 것으로 간주할 수 있으며 이로 인해 비즈니스 손실이 발생할 수 있습니다. 데이터 불일치 또는 기타 현상이 발생합니다. 그러나 RPOPLPUSH 명령을 사용하면 소비자 프로그램은 기본 메시지 큐에서 메시지를 검색한 후 백업 큐에 메시지를 삽입하고, 소비자 프로그램이 정상적인 처리 논리를 완료한 후 백업 큐에서 메시지를 삭제합니다. 동시에 데몬 프로세스도 제공할 수 있습니다. 백업 대기열의 메시지가 만료된 것으로 확인되면 다른 소비자 프로그램이 계속 처리할 수 있도록 해당 메시지를 기본 메시지 대기열에 다시 넣을 수 있습니다.
위는 Redis 튜토리얼입니다. (3): List 데이터 유형에 대한 자세한 내용은 PHP 중국어 웹사이트(www.php.cn)를 참고하세요!