이 글은 Redis의 데이터 유형에 대한 관련 지식을 제공하며, 주로 일반적인 데이터 유형 사용 시나리오와 관련된 문제를 소개합니다.
추천 학습: Redis 학습 튜토리얼
Redis 데이터 유형 및 사용 시나리오
다른 KV 데이터베이스와 비교할 때 Redis의 주요 기능 중 하나는 다음과 같습니다. 풍부한 데이터 유형을 지원합니다. 총 5가지 데이터 유형을 지원하며, 이 5가지 데이터 유형과 각각의 사용 시나리오 및 내부 구현을 하나씩 소개합니다.
string
소개: 문자열 유형은 Redis에서 가장 기본적인 데이터 유형으로 가장 일반적으로 사용되는 데이터 유형이며 많은 플레이어가 Redis의 유일한 데이터 유형으로 사용하기도 합니다. 문자열 유형은 Redis에서 바이너리 안전합니다. 즉, 문자열 값은 바이너리 문자열에 관심이 있고 특정 형식에는 관심이 없습니다. 이를 사용하여 json 형식이나 JPEG 이미지 형식으로 문자열을 저장할 수 있습니다.
문자열 길이 가져오기
문자열에 내용 추가
문자열의 특정 내용을 설정하고 가져오기
문자열의 특정 비트를 설정하고 가져오기
설정 일련의 문자열 내용을 일괄적으로
일반적인 명령: set, get, decr, incr, mget 등
애플리케이션 시나리오:
(1) MySQL에 필드 값 저장
키를 테이블 이름으로 설계: 기본 키 이름: 기본 키 값: 필드 이름
(2) 객체 저장
문자열 유형은 다음을 지원합니다. 모든 형식의 문자열은 json 또는 기타 개체 형식의 문자열을 저장하는 데 가장 일반적으로 사용됩니다. (이 시나리오에서는 해시 데이터 유형을 사용하는 것이 좋습니다)
set user:id:1 '[{"id":1,"name":"zj","email":"156577812@qq.com"},{"id":1,"name":"zj","email":"156577812@qq.com"}]'
(3) 자동 증가 ID 생성
redis의 문자열 유형 값이 정수 형식인 경우 redis는 자동 증가를 위해 이를 정수로 처리할 수 있습니다. (증가) 및 자동 감소(감소) 연산. 모든 Redis 작업은 원자성이므로 여러 클라이언트가 연결할 때 발생할 수 있는 트랜잭션 문제에 대해 걱정할 필요가 없습니다.
일반적으로 사용되는 명령: hget, hset, hgetall 등
응용 시나리오:
사용자 정보와 같은 구조화된 데이터 저장. Memcached나 CKV에서는 사용자의 닉네임, 나이, 성별, 포인트 등의 사용자 정보를 먼저 직렬화하여 문자열 값으로 저장해야 하는데, 이때 항목 중 하나를 수정해야 합니다. , 일반적으로 값을 꺼내고 역직렬화한 후 항목의 값을 수정한 다음 직렬화하여 다시 저장해야 합니다. 이는 오버헤드를 증가시킬 뿐만 아니라 동시 작업이 가능한 상황(예: 두 개의 동시 작업에 포인트 수정이 필요한 경우)에도 적합하지 않습니다. Redis의 해시 구조를 사용하면 데이터베이스의 속성을 업데이트하는 것처럼 특정 속성 값만 수정할 수 있습니다. 아래와 같이
Key는 사용자 ID, value는 Map, 이 Map의 key는 구성원의 속성 이름, value는 속성 값을 통해 데이터 수정 및 접근이 가능합니다. 내부 맵의 키(Redis 내부 맵의 키를 필드라고 함)를 통해 직접, 즉 해당 속성 데이터를 키(사용자 ID) + 필드(속성 라벨)를 통해 조작할 수 있습니다. 데이터를 저장하며 직렬화 및 동시 수정 제어 문제가 발생하지 않습니다.
단, 여기서 주의할 점은 Redis는 모든 속성 데이터를 직접 얻을 수 있는 인터페이스(hgetall)를 제공한다는 점입니다. 그러나 내부 Map의 구성원이 많은 경우 내부 Map 전체를 순회하는 작업이 필요합니다. Redis의 단일 스레드 모델에서는 순회 작업에 시간이 많이 걸릴 수 있으며 다른 클라이언트의 요청에 전혀 응답하지 않을 수 있습니다.
인덱스를 구축하는 데 사용할 수 있습니다. 예를 들어, ID 외에도 User 개체를 이름으로 쿼리해야 하는 경우가 있습니다. User 개체를 삽입할 때(user:101{"id":101 설정) user:name:id 키를 사용하여 해시를 구축할 수 있습니다. ,"name":"calvin ”}) 그런데 이 해시에 항목을 삽입합니다(hset user:name:id calvin 101). 이때 calvin은 해시의 키로 사용되며 값은 다음과 같습니다. 101. 이름으로 쿼리할 때 hgetuser:name:id calvin을 사용하여 calvin이라는 키에서 ID를 가져옵니다. 특정 데이터 조각을 찾기 위해 여러 인덱스를 사용해야 하는 경우 하나의 해시 키를 사용하면 여러 문자열 키를 사용하여 인덱스 값을 저장하는 것을 피할 수 있습니다.
HINCRBY를 사용하여 idmaker를 구현할 수도 있습니다. 문자열 유형의 idmaker와 비교하면 각 유형에는 키가 필요하고 해시 유형에는 키가 하나만 필요합니다.
해시 데이터 형식은 위 형식의 데이터를 저장할 때 문자열 형식보다 유연하고 빠르다는 장점이 있습니다. 특히 문자열 형식을 사용하여 저장하는 경우에도 문자열을 json 형식으로 변환하고 구문 분석해야 합니다. 변환이 필요하지 않습니다. 메모리 오버헤드 측면에서는 해시가 여전히 유리합니다.
구현 방법:
Value에 해당하는 Redis Hash는 실제로 내부에 HashMap입니다. 여기에는 두 가지 다른 구현이 있습니다. Hash의 멤버 수가 적을 경우 Redis는 메모리를 절약하기 위해 1차원 배열과 같은 방법을 사용하여 이를 콤팩트하게 저장합니다. 실제 HashMap 구조입니다. 해당 값 redisObject의 인코딩은 zipmap입니다. 멤버 수가 증가하면 자동으로 실제 HashMap으로 변환됩니다.
소개:
목록은 삽입 순서로 정렬된 문자열 연결 목록입니다. 새 요소는 머리와 꼬리에 삽입될 수 있습니다(이중 연결 목록 구현, 양쪽 끝에 요소를 추가하는 시간 복잡도). O(1))입니다. 요소를 삽입할 때 키가 존재하지 않으면 Redis는 해당 키에 대한 새 연결 목록을 생성합니다. 연결 목록의 모든 요소가 제거되면 해당 키도 Redis에서 제거됩니다.
일반적으로 사용되는 명령: lpush, rpush, lpop, rpop, lrange 등
적용 시나리오:
Twitter의 팔로우 목록, 팬 목록 등 다양한 목록, 최신 뉴스 순위, 각 기사에 대한 댓글 등도 Redis의 목록 구조를 사용하여 구현할 수 있습니다.
메시지 대기열에서는 목록의 PUSH 작업을 사용하여 목록에 작업을 저장할 수 있으며, 그런 다음 작업자 스레드는 POP 작업을 사용하여 실행할 작업을 꺼냅니다. 여기의 메시지 대기열에는 확인 메커니즘이 없습니다. 소비자가 Pop에 작업을 제공하고 작업을 완료하기 전에 충돌이 발생하면 어떻게 될까요? 한 가지 해결책은 배포할 때 이를 목록과 정렬된 집합 모두에 동시에 보내는 것입니다. 사용자가 작업을 완료한 후에는 ZREM을 사용하여 제거해야 합니다. 정렬된 세트의 작업을 제거하고 시간이 초과된 완료되지 않은 작업을 제거하고 목록에 다시 넣습니다. 또 다른 접근 방식은 각 작업자에 대한 추가 목록을 추가하고, 작업을 표시할 때 RPopLPush를 사용하고, 동시에 작업자의 목록에 작업을 넣고, 완료되면 LREM을 사용하여 제거하는 것입니다. 클러스터 관리(예: 사육사)가 작업자가 사망한 것을 발견하면 작업자의 목록 내용이 기본 목록으로 반환됩니다.
LRANGE를 사용하면 목록 콘텐츠의 페이징 기능을 쉽게 구현할 수 있습니다.
최신 N 데이터를 가져오는 작업: LPUSH를 사용하여 콘텐츠 ID를 삽입하고 목록 선두에 키워드로 저장합니다. LTRIM은 목록의 항목 수를 최대 5000개로 제한하는 데 사용됩니다. 사용자가 검색해야 하는 데이터의 양이 이 캐시 용량을 초과하는 경우 요청을 데이터베이스로 보내야 합니다.
구현 방법:
Redis 목록은 역방향 검색과 순회를 지원할 수 있는 양방향 연결 목록으로 구현되어 작업이 더 편리해집니다. 그러나 일부 추가 메모리 오버헤드가 발생하고 전송을 포함하여 Redis 내부에 많은 구현이 수행됩니다. 버퍼 큐 등. 이 데이터 구조도 사용됩니다.
소개: 집합의 요소는 순서가 없으며 반복되지 않습니다. 중복된 요소를 세트에 넣으면 자동으로 제거됩니다.
일반적으로 사용되는 명령:
sadd, spop, smembers, sunion 등
응용 시나리오:
중복 제거가 필요한 일부 목록과 세트는 구성원이 세트 컬렉션에 있는지 확인하는 중요한 인터페이스를 제공합니다. 이는 목록이 제공할 수 없는 것입니다.
일부 집단 데이터는 저장될 수 있습니다. 예를 들어 Weibo 애플리케이션에서는 사용자의 모든 팔로어가 컬렉션에 저장될 수 있으며 모든 팬이 컬렉션에 저장될 수 있습니다. Redis는 또한 컬렉션에 대한 교차, 결합 및 차이와 같은 작업을 제공하므로 공동 관심, 공통 선호도 및 2차 친구와 같은 기능을 구현하는 데 매우 편리할 수 있습니다. 위의 모든 컬렉션 작업에 대해 다른 명령을 사용할 수도 있습니다. 결과를 클라이언트에 반환하거나 새 컬렉션에 저장합니다. 또 다른 예로, QQ에는 "친구 태그"라는 소셜 기능이 있습니다. "큰 아름다움", "거물", "Ouba" 등과 같은 친구를 태그할 수 있습니다. 여기서 각 사용자의 태그를 컬렉션 내에 저장할 수도 있습니다. .
특정 페이지를 방문한 특정 등록 사용자 또는 IP 주소 수를 알고 싶다면 SADD page:day1:
구현 방법:
세트의 내부 구현은 값이 항상 null인 HashMap입니다. 실제로 해시를 계산하여 개체를 빠르게 정렬할 수 있습니다.
소개: Sorted set, set과 비교하여 요소를 set에 넣을 때 해당 요소의 점수도 제공하며, 점수에 따라 자동으로 정렬할 수 있습니다.
일반적인 명령:
zadd, zrange, zrem, zcard 등
사용 시나리오:
순서가 지정되고 중복되지 않는 컬렉션 목록을 저장합니다. 예를 들어 Twitter의 공개 타임라인은 게시 시간을 점수로 저장할 수 있습니다. , 그래서 얻을 수 있습니다. 시간은 자동으로 시간별로 정렬됩니다.
가중 대기열을 만들 수 있습니다. 예를 들어 일반 메시지의 점수는 1이고 중요한 메시지의 점수는 2입니다. 그런 다음 작업자 스레드는 점수의 역순으로 작업 작업을 가져오도록 선택할 수 있습니다. 중요한 작업의 우선순위를 정하세요.
만료된 항목 처리: 목록을 시간별로 정렬하려면 Unix 시간을 핵심으로 사용하세요. 만료된 항목을 찾는 어려운 작업을 완료하려면 current_time 및 time_to_live를 검색하세요. 또 다른 백그라운드 작업은 ZRANGE...WITHSCORES를 사용하여 만료된 항목을 쿼리하고 삭제합니다.
구현 방법:
Redis 정렬 세트는 내부적으로 HashMap 및 건너뛰기 목록(SkipList)을 사용하여 데이터의 저장 및 순서를 보장하며 건너뛰기 목록은 모든 구성원을 저장합니다. HashMap에 저장된 점수는 점프 테이블 구조를 사용하여 검색 효율성을 높일 수 있으며 구현이 비교적 간단합니다.
추천 학습: Redis 비디오 튜토리얼
위 내용은 Redis 데이터 유형 및 사용 시나리오 요약의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!