Tất cả các câu trả lời (tại thời điểm viết bài này) giả sử mỗi Redis, MongoDB và có lẽ một cơ sở dữ liệu quan hệ dựa trên SQL về cơ bản là cùng một công cụ: "lưu trữ dữ liệu". Họ không xem xét mô hình dữ liệu nào cả.
MongoDB: Dữ liệu phức tạp
MongoDB là một cửa hàng tài liệu. Để so sánh với cơ sở dữ liệu quan hệ dựa trên SQL: cơ sở dữ liệu quan hệ đơn giản hóa các tệp CSV được lập chỉ mục, mỗi tệp là một bảng; lưu trữ tài liệu đơn giản hóa thành các tệp JSON được lập chỉ mục, mỗi tệp là một tài liệu, với nhiều tệp được nhóm lại với nhau.
Các tệp JSON có cấu trúc tương tự như các tệp XML và YAML và từ điển như trong Python, vì vậy hãy nghĩ về dữ liệu của bạn trong loại phân cấp đó. Khi lập chỉ mục, cấu trúc là khóa: Một tài liệu chứa các khóa được đặt tên, chứa các tài liệu, mảng hoặc giá trị vô hướng. Hãy xem xét các tài liệu dưới đây.
{
_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"
}
Các tài liệu trên có một khóa, PhoneNumber.Mobile
có giá trị 555 634-5789
. Bạn có thể tìm kiếm thông qua một bộ sưu tập các tài liệu trong đó khóa PhoneNumber.Mobile
, có một số giá trị; chúng được lập chỉ mục.
Nó cũng có một mảng Accounts
chứa nhiều chỉ mục. Có thể truy vấn tài liệu Accounts
chứa chính xác một số tập hợp con các giá trị, tất cả một tập hợp con các giá trị hoặc bất kỳ tập hợp con nào của các giá trị. Điều đó có nghĩa là bạn có thể tìm kiếm Accounts = ["379-1111", "379-2574"]
và không tìm thấy ở trên; bạn có thể tìm kiếm Accounts includes ["379-1111"]
và tìm tài liệu trên; và bạn có thể tìm kiếm Accounts includes any of ["974-3785","414-6731"]
và tìm tài liệu trên và bất kỳ tài liệu nào bao gồm tài khoản "974-3785", nếu có.
Tài liệu đi sâu như bạn muốn. PhoneNumber.Mobile
có thể chứa một mảng, hoặc thậm chí là một tài liệu phụ ( PhoneNumber.Mobile.Work
và PhoneNumber.Mobile.Personal
). Nếu dữ liệu của bạn có cấu trúc cao, tài liệu là một bước tiến lớn từ cơ sở dữ liệu quan hệ.
Nếu dữ liệu của bạn chủ yếu bằng phẳng, có quan hệ và được cấu trúc chặt chẽ, bạn nên sử dụng cơ sở dữ liệu quan hệ. Một lần nữa, dấu hiệu lớn là liệu mô hình dữ liệu của bạn phù hợp nhất với tập hợp các tệp CSV có liên quan đến nhau hay tập hợp các tệp XML / JSON / YAML.
Đối với hầu hết các dự án, bạn sẽ phải thỏa hiệp, chấp nhận một công việc nhỏ ở một số khu vực nhỏ nơi SQL hoặc Kho lưu trữ tài liệu không phù hợp; đối với một số dự án lớn, phức tạp lưu trữ một lượng lớn dữ liệu (nhiều cột; các hàng không liên quan), sẽ rất hợp lý khi lưu trữ một số dữ liệu trong một mô hình và dữ liệu khác trong một mô hình khác. Facebook sử dụng cả SQL và cơ sở dữ liệu đồ thị (nơi dữ liệu được đưa vào các nút và các nút được kết nối với các nút khác); Craigslist đã từng sử dụng MySQL và MongoDB, nhưng đã tìm cách chuyển hoàn toàn sang MongoDB. Đây là những nơi mà khoảng cách và mối quan hệ của dữ liệu phải đối mặt với các khuyết tật đáng kể nếu được đặt trong một mô hình.
Redis: Khóa-Giá trị
Redis, về cơ bản, là một cửa hàng khóa-giá trị. Redis cho phép bạn cung cấp cho nó một khóa và tìm kiếm một giá trị duy nhất. Bản thân Redis có thể lưu trữ chuỗi, danh sách, băm và một vài thứ khác; Tuy nhiên, nó chỉ tìm kiếm theo tên.
Vô hiệu bộ nhớ cache là một trong những vấn đề khó khăn của khoa học máy tính; cái khác là đặt tên. Điều đó có nghĩa là bạn sẽ sử dụng Redis khi bạn muốn tránh hàng trăm lượt tra cứu dư thừa cho một back-end, nhưng bạn sẽ phải tìm ra khi nào bạn cần một cái nhìn mới.
Trường hợp không hợp lệ rõ ràng nhất là cập nhật về ghi: nếu bạn đọc user:Simon:lingots = NOTFOUND
, bạn có thể SELECT Lingots FROM Store s INNER JOIN UserProfile u ON s.UserID = u.UserID WHERE u.Username = Simon
và lưu trữ kết quả 100
, như SET user:Simon:lingots = 100
. Sau đó, khi bạn giải thưởng Simon 5 lingots, bạn đọc user:Simon:lingots = 100
, SET user:Simon:lingots = 105
và UPDATE Store s INNER JOIN UserProfile u ON s.UserID = u.UserID SET s.Lingots = 105 WHERE u.Username = Simon
. Bây giờ bạn có 105 trong cơ sở dữ liệu của bạn và trong Redis, và có thể lấy user:Simon:lingots
mà không cần truy vấn cơ sở dữ liệu.
Trường hợp thứ hai là cập nhật thông tin phụ thuộc. Giả sử bạn tạo các đoạn của trang và lưu trữ đầu ra của chúng. Tiêu đề cho thấy kinh nghiệm, cấp độ và số tiền của người chơi; Trang hồ sơ của người chơi có một khối hiển thị số liệu thống kê của họ; và kể từ đó trở đi. Người chơi có được một số kinh nghiệm. Chà, bây giờ bạn có một vài templates:Header:Simon
,templates:StatsBox:Simon
, templates:GrowthGraph:Simon
, và vân vân các lĩnh vực nơi bạn đã lưu trữ các sản phẩm của một nửa tá cơ sở dữ liệu truy vấn chạy qua một mẫu động cơ. Thông thường, khi bạn hiển thị các trang này, bạn nói:
$t = GetStringFromRedis("templates:StatsBox:" + $playerName);
if ($t == null) {
$t = BuildTemplate("StatsBox.tmpl",
GetStatsFromDatabase($playerName));
SetStringInRedis("Templates:StatsBox:" + $playerName, $t);
}
print $t;
Bởi vì bạn vừa cập nhật kết quả của GetStatsFromDatabase("Simon")
, bạn phải bỏ templates:*:Simon
bộ đệm khóa-giá trị. Khi bạn cố gắng kết xuất bất kỳ mẫu nào trong số này, ứng dụng của bạn sẽ loại bỏ dữ liệu tìm nạp từ cơ sở dữ liệu của bạn (PostgreQuery, MongoDB) và chèn nó vào mẫu của bạn; sau đó nó sẽ lưu trữ kết quả trong Redis và, hy vọng, không bận tâm thực hiện các truy vấn cơ sở dữ liệu và kết xuất mẫu trong lần tiếp theo nó hiển thị khối đầu ra đó.
Redis cũng cho phép bạn thực hiện hàng đợi tin nhắn đăng ký nhà xuất bản và như vậy. Đó là một chủ đề hoàn toàn khác. Điểm ở đây là Redis là bộ đệm giá trị khóa, khác với cơ sở dữ liệu quan hệ hoặc kho lưu trữ tài liệu.
Phần kết luận
Chọn công cụ của bạn dựa trên nhu cầu của bạn. Nhu cầu lớn nhất thường là mô hình dữ liệu, vì điều đó xác định mức độ phức tạp và dễ bị lỗi của mã của bạn. Các ứng dụng chuyên dụng sẽ dựa vào hiệu suất, nơi bạn viết mọi thứ trong hỗn hợp C và hội; hầu hết các ứng dụng sẽ chỉ xử lý trường hợp tổng quát và sử dụng hệ thống bộ đệm như Redis hoặc Memcached, nhanh hơn rất nhiều so với cơ sở dữ liệu SQL hiệu suất cao hoặc kho lưu trữ tài liệu.