이 글을 쓰는 시점의 모든 답변은 각 Redis, MongoDB 및 SQL 기반 관계형 데이터베이스가 본질적으로 동일한 도구 인 "데이터 저장"이라고 가정합니다. 그들은 데이터 모델을 전혀 고려하지 않습니다.
MongoDB : 복잡한 데이터
MongoDB는 문서 저장소입니다. SQL 기반 관계형 데이터베이스와 비교 : 관계형 데이터베이스는 색인화 된 CSV 파일로 단순화합니다. 각 파일은 테이블입니다. 문서 저장소는 색인화 된 JSON 파일로 단순화하며, 각 파일은 문서이며 여러 파일이 함께 그룹화됩니다.
JSON 파일은 구조가 XML 및 YAML 파일과 비슷하며 Python과 같은 사전과 유사하므로 이러한 종류의 계층 구조에서 데이터를 생각하십시오. 인덱싱 할 때 구조는 키입니다. 문서에는 추가 문서, 배열 또는 스칼라 값을 포함하는 명명 된 키가 포함됩니다. 아래 문서를 고려하십시오.
{
_id: 0x194f38dc491a,
Name: "John Smith",
PhoneNumber:
Home: "555 999-1234",
Work: "555 999-9876",
Mobile: "555 634-5789"
Accounts:
- "379-1111"
- "379-2574"
- "414-6731"
}
위의 문서에는 키 PhoneNumber.Mobile
가 있으며 값은 555 634-5789
입니다. , 키에 PhoneNumber.Mobile
값이 있는 문서 모음을 검색 할 수 있습니다 . 그들은 색인됩니다.
또한 Accounts
여러 인덱스를 보유 하는 배열이 있습니다. 이 문서를 조회 할 수 있습니다 Accounts
포함 정확하게 , 일부 값 집합을 모든 가치의 일부 부분 집합의, 또는 어떤 값의 일부 하위 집합. 즉 Accounts = ["379-1111", "379-2574"]
, 위를 검색 하고 찾을 수 없습니다. Accounts includes ["379-1111"]
위의 문서를 검색 하고 찾을 수 있습니다. Accounts includes any of ["974-3785","414-6731"]
위의 문서와 "974-3785"계정이있는 문서를 검색 하고 찾을 수 있습니다 (있는 경우).
문서는 원하는만큼 깊어집니다. PhoneNumber.Mobile
배열 또는 하위 문서 ( PhoneNumber.Mobile.Work
및 PhoneNumber.Mobile.Personal
)를 보유 할 수 있습니다 . 데이터가 고도로 구조화 된 경우 관계형 데이터베이스에서 문서가 크게 향상됩니다.
데이터가 대부분 평평하고 관계형이며 엄격하게 구조화 된 경우 관계형 데이터베이스를 사용하는 것이 좋습니다. 다시 말하지만, 데이터 모델이 서로 관련된 CSV 파일 모음 또는 XML / JSON / YAML 파일 모음에 가장 적합한 지 여부가 큰 신호입니다.
대부분의 프로젝트의 경우 SQL 또는 문서 저장소가 맞지 않는 일부 작은 영역에서 약간의 해결 방법을 받아 들여 타협해야합니다. 광범위한 데이터 분산 (많은 열; 행은 관련이 없음)을 저장하는 크고 복잡한 프로젝트의 경우 일부 데이터를 한 모델에 저장하고 다른 데이터를 다른 모델에 저장하는 것이 좋습니다. Facebook은 SQL과 그래프 데이터베이스를 모두 사용합니다 (데이터는 노드에 배치되고 노드는 다른 노드에 연결됨). Craigslist는 MySQL과 MongoDB를 사용했지만 MongoDB로 전적으로 이동하려고했습니다. 하나의 모델에 놓으면 데이터의 범위와 관계가 심각한 핸디캡에 직면하는 곳입니다.
Redis : 키-값
Redis는 가장 기본적으로 키-값 저장소입니다. Redis를 사용하면 키를 제공하고 단일 값을 찾을 수 있습니다. Redis 자체는 문자열, 목록, 해시 및 기타 몇 가지를 저장할 수 있습니다. 그러나 이름 만 찾습니다.
캐시 무효화는 컴퓨터 과학의 어려운 문제 중 하나입니다. 다른 하나는 이름을 짓는 것입니다. 즉, 백엔드에 대한 수백 번의 과도한 조회를 피하고 싶을 때 Redis를 사용하지만 새로운 조회가 필요한 시점을 파악해야합니다.
무효의 가장 눈에 띄는 경우가 쓰기에 대한 업데이트입니다 : 당신이 읽는다면 user:Simon:lingots = NOTFOUND
, 당신은 할 수 SELECT Lingots FROM Store s INNER JOIN UserProfile u ON s.UserID = u.UserID WHERE u.Username = Simon
및 결과를 저장 100
로 SET user:Simon:lingots = 100
. 당신은 사이먼 5 lingots을 수여 할 때 다음, 당신은 읽고 user:Simon:lingots = 100
, SET user:Simon:lingots = 105
하고 UPDATE Store s INNER JOIN UserProfile u ON s.UserID = u.UserID SET s.Lingots = 105 WHERE u.Username = Simon
. 이제 데이터베이스와 Redis에 105가 있으며 데이터베이스 user:Simon:lingots
를 쿼리하지 않고도 얻을 수 있습니다 .
두 번째 경우는 종속 정보를 업데이트하는 것입니다. 페이지 청크를 생성하고 출력을 캐시한다고 가정 해 봅시다. 헤더에는 플레이어의 경험, 레벨 및 금액이 표시됩니다. 플레이어의 프로필 페이지에는 통계를 보여주는 블록이 있습니다. 기타 등등. 플레이어는 약간의 경험을 얻습니다. 자, 이제 당신은 몇 가지가있다 templates:Header:Simon
, templates:StatsBox:Simon
, templates:GrowthGraph:Simon
당신이 쿼리 템플릿 엔진을 통해 실행 대여섯 데이터베이스의 출력을 캐시 한 곳 등이 필드. 일반적으로 이러한 페이지를 표시하면 다음과 같이 말합니다.
$t = GetStringFromRedis("templates:StatsBox:" + $playerName);
if ($t == null) {
$t = BuildTemplate("StatsBox.tmpl",
GetStatsFromDatabase($playerName));
SetStringInRedis("Templates:StatsBox:" + $playerName, $t);
}
print $t;
의 결과를 방금 업데이트 했으므로 키-값 캐시 GetStatsFromDatabase("Simon")
에서 삭제 templates:*:Simon
해야합니다. 이러한 템플릿을 렌더링하려고하면 응용 프로그램에서 데이터베이스 (PostgreSQL, MongoDB)에서 데이터를 가져 와서 템플릿에 삽입합니다. 그런 다음 결과를 Redis에 저장하고 다음에 해당 출력 블록을 표시 할 때 데이터베이스 쿼리 및 렌더링 템플릿을 작성하지 않아도됩니다.
또한 Redis를 사용하면 게시자 구독 메시지 큐 등을 수행 할 수 있습니다. 그것은 또 다른 주제입니다. 여기서 Redis는 키-값 캐시이며 관계형 데이터베이스 또는 문서 저장소와 다릅니다.
결론
필요에 따라 도구를 선택하십시오. 코드가 얼마나 복잡하고 오류가 발생하기 쉬운 지 결정하기 때문에 가장 큰 요구는 일반적으로 데이터 모델입니다. 전문화 된 응용 프로그램은 성능과 C 및 어셈블리를 혼합하여 모든 것을 쓰는 장소에 의존합니다. 대부분의 응용 프로그램은 일반화 된 사례를 처리하고 고성능 SQL 데이터베이스 나 문서 저장소보다 훨씬 빠른 Redis 또는 Memcached와 같은 캐싱 시스템을 사용합니다.