Python을 사용하여 Redis 데이터베이스의 모든 키 가져오기
사용 가능한 모든 키를 얻기 위해 Redis 명령에 대한 게시물이 있지만, 저는 그것을 Python으로 하고 싶습니다.
이거 할 수 있는 방법은?
사용하다scan_iter()
scan_iter()
보다 우수함keys()
모든 키를 메모리에 로드하는 대신 사용할 수 있는 반복기를 제공하기 때문에 많은 키에 사용할 수 있습니다.
레디스에 1B 레코드가 있어서 모든 키를 한 번에 돌려줄 만큼의 메모리를 얻을 수 없었습니다.
키를 하나씩 스캔
다음은 다음을 사용하는 파이썬 스니펫입니다.scan_iter()
스토어에서 패턴과 일치하는 모든 키를 가져와 하나씩 삭제하는 방법:
import redis
r = redis.StrictRedis(host='localhost', port=6379, db=0)
for key in r.scan_iter("user:*"):
# delete the key
r.delete(key)
일괄 검색
검색할 키 목록이 매우 많은 경우(예: >100k 키보다 큰 경우) 다음과 같이 일괄적으로 검색하는 것이 더 효율적입니다.
import redis
from itertools import izip_longest
r = redis.StrictRedis(host='localhost', port=6379, db=0)
# iterate a list in batches of size n
def batcher(iterable, n):
args = [iter(iterable)] * n
return izip_longest(*args)
# in batches of 500 delete keys matching user:*
for keybatch in batcher(r.scan_iter('user:*'),500):
r.delete(*keybatch)
저는 이 스크립트를 벤치마킹하여 배치 크기 500을 사용하는 것이 키를 하나씩 스캔하는 것보다 5배 더 빠르다는 것을 발견했습니다.다양한 배치 크기(3,50,500,1000,5000)를 테스트한 결과 배치 크기가 500개가 최적인 것으로 보입니다.
사용 여부에 유의하십시오.scan_iter()
또는keys()
메소드, 작업이 원자적이지 않으며 부분적으로 실패할 수 있습니다.
명령줄에서 XARG를 사용하지 마십시오.
다른 곳에서 반복되는 이 예는 추천하지 않습니다.유니코드 키의 경우 실패하고 적당한 수의 키의 경우에도 매우 느립니다.
redis-cli --raw keys "user:*"| xargs redis-cli del
이 예에서 xargs는 모든 키에 대해 새 redis-cli 프로세스를 생성합니다. 이것은 좋지 않습니다.
저는 이 접근 방식을 모든 키를 하나씩 삭제한 첫 번째 파이썬 예제보다 4배 느리고 500개 묶음으로 삭제하는 것보다 20배 느립니다.
예, StrictRedis 모듈에서 사용합니다.
>>> import redis
>>> r = redis.StrictRedis(host=YOUR_HOST, port=YOUR_PORT, db=YOUR_DB)
>>> r.keys()
null 패턴을 지정하면 모든 패턴이 가져옵니다.링크된 페이지에 따라:
키(키='*')
패턴과 일치하는 키 목록을 반환합니다.
import redis
r = redis.Redis("localhost", 6379)
for key in r.scan_iter():
print key
Pyredis 라이브러리 사용
2.8.0 이후에 사용할 수 있습니다.
시간 복잡도: 모든 통화에 대해 O(1).커서가 0으로 돌아갈 만큼의 명령 호출을 포함하여 전체 반복에 대한 O(N).N은 집합 내부의 요소 수입니다.
패트릭의 답변과 다른 것들에 맞는 예시 코드를 추가하고 싶습니다.
키와 scan_iter 기법을 모두 사용하여 결과를 표시합니다.그리고 Python3는 izip_longest 대신 zip_longest를 사용합니다.아래 코드는 모든 키를 순환하여 표시합니다.저는 출력을 줄이기 위해 배치 크기를 변수로 12로 설정했습니다.
저는 키 배치가 어떻게 작동하는지 더 잘 이해하기 위해 이 글을 썼습니다.
import redis
from itertools import zip_longest
\# connection/building of my redisObj omitted here
\# iterate a list in batches of size n
def batcher(iterable, n):
args = [iter(iterable)] * n
return zip_longest(*args)
result1 = redisObj.get("TestEN")
print(result1)
result2 = redisObj.get("TestES")
print(result2)
print("\n\nLoop through all keys:")
keys = redisObj.keys('*')
counter = 0
print("len(keys)=", len(keys))
for key in keys:
counter +=1
print (counter, "key=" +key, " value=" + redisObj.get(key))
print("\n\nLoop through all keys in batches (using itertools)")
\# in batches of 500 delete keys matching user:*
counter = 0
batch_counter = 0
print("Try scan_iter:")
for keybatch in batcher(redisObj.scan_iter('*'), 12):
batch_counter +=1
print(batch_counter, "keybatch=", keybatch)
for key in keybatch:
if key != None:
counter += 1
print(" ", counter, "key=" + key, " value=" + redisObj.get(key))
출력 예:
Loop through all keys:
len(keys)= 2
1 key=TestES value=Ola Mundo
2 key=TestEN value=Hello World
Loop through all keys in batches (using itertools)
Try scan_iter:
1 keybatch= ('TestES', 'TestEN', None, None, None, None, None, None, None, None, None, None)
1 key=TestES value=Ola Mundo
2 key=TestEN value=Hello World
rediscommand는 단일 스레드이므로 키()를 누르면 다른 rediscovery 작업을 차단할 수 있습니다.자세한 내용은 Redis에서 SCAN과 KEIES 성능 비교를 설명하는 훌륭한 게시물을 참조하십시오.
위의 승인된 답변에 추가합니다.
scan_iter
와 함께 사용할 수 있습니다.count
매개 변수를 사용하여 redis에 단일 반복 동안 여러 키를 검색하도록 지시합니다.이를 통해 특히 일치하는 패턴과 큰 키 공간에서 사용할 경우 키 가져오기 속도가 크게 향상됩니다.
카운트에 매우 높은 값을 사용할 경우 다른 동시 쿼리의 성능이 저하될 수 있으므로 엄격하게 사용해야 합니다.
https://docs.keydb.dev/blog/2020/08/10/blog-post/ 자세한 내용과 몇 가지 벤치마크가 있는 기사가 있습니다.
패트릭과 닐의 코드를 개선하고 csv에 내보내기를 추가했습니다.
import csv
import redis
from itertools import zip_longest
redisObj = redis.StrictRedis(host='localhost', port=6379, db=0, decode_responses=True)
searchStr = ""
# iterate a list in batches of size n
def batcher(iterable, n):
args = [iter(iterable)] * n
return zip_longest(*args)
with open('redis.csv', 'w', newline='') as csvfile:
fieldnames = ['key', 'value']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
print("\n\nLoop through all keys in batches (using itertools)")
counter = 0
batch_counter = 0
print("Try scan_iter:")
for keybatch in batcher(redisObj.scan_iter('*'), 500):
batch_counter +=1
#print(batch_counter, "keybatch=", keybatch)
for key in keybatch:
if key != None:
counter += 1
val = ""
if (searchStr in key):
valType = redisObj.type(key)
print(valType)
match valType:
case "string":
val = redisObj.get(key)
case "list":
valList = redisObj.lrange(key, 0, -1)
val = '\n'.join(valList)
case "set":
valList = redisObj.smembers(key)
val = '\n'.join(valList)
case "zset":
valDict = redisObj.zrange(key, 0, -1, False, True)
val = '\n'.join(['='.join(i) for i in valDict.items()])
case "hash":
valDict = redisObj.hgetall(key)
val = '\n'.join(['='.join(i) for i in valDict.items()])
case "stream":
val = ""
case _:
val = ""
print(" ", counter, "key=" + key, " value=" + val)
writer.writerow({'key': key, 'value': val})
언급URL : https://stackoverflow.com/questions/22255589/get-all-keys-in-redis-database-with-python
'source' 카테고리의 다른 글
$document.ready()에 해당하는 Angular2 (0) | 2023.08.04 |
---|---|
pypi 사용자 경고:알 수 없는 배포 옵션: 'install_requires' (0) | 2023.08.04 |
MVC와 같은 WebForms에서 데이터를 루프하는 방법 (0) | 2023.08.04 |
.dex 파일의 메서드 참조 수는 64k API 17을 초과할 수 없습니다. (0) | 2023.08.04 |
컨테이너 자체 내에서 Docker Linux 컨테이너 정보를 가져오려면 어떻게 해야 합니까? (0) | 2023.08.04 |