Python의 Redis 목록에서 여러 항목을 원자적으로 팝핑
뭐하는거야?
Redis의 목록에서 여러 항목을 원자적으로 팝하고 제거하려고 합니다.
뭐?
목록을 고려하십시오: 0 1 2 3 4 5
처음 3개 항목의 결과를 반환한 다음 해당 항목을 제거하고 싶습니다. 또한 결과를 반환하고 목록에서 결과를 제거하는 사이에 목록이 변경되지 않도록 해야 합니다.
예
다음 예를 고려하십시오.
> RPUSH mykey 0 1 2 3 4 5
(integer) 6
> LRANGE mykey 0 2
1) "0"
2) "1"
3) "2"
> LTRIM mykey 3 -1
OK
> LRANGE mykey 0 99
1) "3"
2) "4"
3) "5"
이것은 당신이 당신의 목록을 조작하는 유일한 사람일 때 잘 작동합니다. 그러나 다른 사람이 동시에 목록을 조작하는 경우에는 어떻게 될까요?
> RPUSH mykey 0 1 2 3 4 5
(integer) 6
> LRANGE mykey 0 2
1) "0"
2) "1"
3) "2"
> LTRIM mykey 3 -1
OK
> LRANGE mykey 0 99
(empty array)
어 오. B라고 부를 또 다른 소비자는 실행LRANGE mykey 0 2
하고 수신0 1 2
했습니다. 우리는 그 직후에 같은 명령을 실행했고 같은 결과를 받았습니다. 소비자 B는 이제 LTRIM mykey 3 -1
실행되고 우리도 실행합니다. 이제 목록은 비어 있지만 두 소비자 모두 목록의 처음 3개 항목만 받았습니다. 마지막 3명이 사라졌습니다.
해결책
이 두 트랜잭션 LRANGE
및 LTRIM
가 원자성이어야 합니다. 즉, 둘 다 실행하거나 둘 다 실행하지 않습니다. Redis에서는 transactions 을 사용하여 이를 달성할 수 있습니다. 트랜잭션의 모든 명령은 직렬화되고 순차적으로 실행됩니다. Redis 트랜잭션이 실행되는 도중에 다른 클라이언트가 발행한 요청이 처리되는 일은 절대 있을 수 없습니다. 이렇게 하면 명령이 격리된 단일 작업으로 실행됩니다.
Redis CLI를 사용하는 경우 코드를 다음과 같이 변경합니다.
> MULTI
OK
> RPUSH mykey 0 1 2 3 4 5
QUEUED
> LTRIM mykey 3 -1
QUEUED
> EXEC
1) (integer) 6
2) OK
파이썬에서
실제로 CLI를 사용하는 사람은 없기 때문에 Python에서 이 작업을 수행해 보겠습니다. 이 스크립트는 redis-py 의 파이프라인 기능을 사용합니다. 파이프라인은 단일 요청에서 서버에 대한 여러 명령 버퍼링을 지원하는 기본 Redis 클래스의 하위 클래스입니다.
>>> import redis
>>> my_key = 'pop_trim_test'
>>> r = redis.Redis(host='localhost', port=6379)
>>> r.rpush(my_key, *[x for x in range(10)])
>>> pipe = r.pipeline()
>>> pipe.lrange(my_key, 0, 3)
>>> pipe.ltrim(my_key, 4, -1)
>>> pipe.execute()
[[b'0', b'1', b'2', b'3'], True]
pipe.execute()
파이프 명령의 결과를 목록으로 순차적으로 반환합니다. 따라서 우리lrange
의 결과가 목록의 첫 번째 항목입니다.
더 나은
애플리케이션이 대기열의 항목을 기다리는 소비자 모델로 작업하는 경우 위 코드는 지속적으로 Redis를 쿼리하기 때문에 문제가 될 수 있습니다. 더 나은 동작은 Redis' blocking pop (BLPOP) function 을 사용하는 것입니다. BLPOP을 사용하면 키가 비어 있으면 다른 클라이언트가 키에 대해 LPUSH 또는 RPUSH 작업을 수행할 때까지 클라이언트가 연결을 차단합니다. 여러 소비자를 처리하는 데 유용한 리소스입니다. 소비자가 BLPOP을 성공적으로 실행한 후 위의 코드를 실행하여 이 작업을 수행할 수 있습니다.
Reference
이 문제에 관하여(Python의 Redis 목록에서 여러 항목을 원자적으로 팝핑), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/ahf90/atomically-popping-multiple-items-from-a-redis-list-in-python-2afa
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
> RPUSH mykey 0 1 2 3 4 5
(integer) 6
> LRANGE mykey 0 2
1) "0"
2) "1"
3) "2"
> LTRIM mykey 3 -1
OK
> LRANGE mykey 0 99
1) "3"
2) "4"
3) "5"
> RPUSH mykey 0 1 2 3 4 5
(integer) 6
> LRANGE mykey 0 2
1) "0"
2) "1"
3) "2"
> LTRIM mykey 3 -1
OK
> LRANGE mykey 0 99
(empty array)
이 두 트랜잭션
LRANGE
및 LTRIM
가 원자성이어야 합니다. 즉, 둘 다 실행하거나 둘 다 실행하지 않습니다. Redis에서는 transactions 을 사용하여 이를 달성할 수 있습니다. 트랜잭션의 모든 명령은 직렬화되고 순차적으로 실행됩니다. Redis 트랜잭션이 실행되는 도중에 다른 클라이언트가 발행한 요청이 처리되는 일은 절대 있을 수 없습니다. 이렇게 하면 명령이 격리된 단일 작업으로 실행됩니다.Redis CLI를 사용하는 경우 코드를 다음과 같이 변경합니다.
> MULTI
OK
> RPUSH mykey 0 1 2 3 4 5
QUEUED
> LTRIM mykey 3 -1
QUEUED
> EXEC
1) (integer) 6
2) OK
파이썬에서
실제로 CLI를 사용하는 사람은 없기 때문에 Python에서 이 작업을 수행해 보겠습니다. 이 스크립트는 redis-py 의 파이프라인 기능을 사용합니다. 파이프라인은 단일 요청에서 서버에 대한 여러 명령 버퍼링을 지원하는 기본 Redis 클래스의 하위 클래스입니다.
>>> import redis
>>> my_key = 'pop_trim_test'
>>> r = redis.Redis(host='localhost', port=6379)
>>> r.rpush(my_key, *[x for x in range(10)])
>>> pipe = r.pipeline()
>>> pipe.lrange(my_key, 0, 3)
>>> pipe.ltrim(my_key, 4, -1)
>>> pipe.execute()
[[b'0', b'1', b'2', b'3'], True]
pipe.execute()
파이프 명령의 결과를 목록으로 순차적으로 반환합니다. 따라서 우리lrange
의 결과가 목록의 첫 번째 항목입니다.더 나은
애플리케이션이 대기열의 항목을 기다리는 소비자 모델로 작업하는 경우 위 코드는 지속적으로 Redis를 쿼리하기 때문에 문제가 될 수 있습니다. 더 나은 동작은 Redis' blocking pop (BLPOP) function 을 사용하는 것입니다. BLPOP을 사용하면 키가 비어 있으면 다른 클라이언트가 키에 대해 LPUSH 또는 RPUSH 작업을 수행할 때까지 클라이언트가 연결을 차단합니다. 여러 소비자를 처리하는 데 유용한 리소스입니다. 소비자가 BLPOP을 성공적으로 실행한 후 위의 코드를 실행하여 이 작업을 수행할 수 있습니다.
Reference
이 문제에 관하여(Python의 Redis 목록에서 여러 항목을 원자적으로 팝핑), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/ahf90/atomically-popping-multiple-items-from-a-redis-list-in-python-2afa텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)