Thành thật mà nói, tôi không thể quyết định đây là câu hỏi SO hay câu hỏi MSO, nhưng:
Chuyển sang hệ thống khác là không bao giờ nhanh hơn truy vấn bộ nhớ cục bộ (miễn là nó được khóa); câu trả lời đơn giản:chúng tôi sử dụng cả hai! Vì vậy, chúng tôi sử dụng:
- bộ nhớ cục bộ
- khác kiểm tra redis và cập nhật bộ nhớ cục bộ
- khác tìm nạp từ nguồn và cập nhật redis và bộ nhớ cục bộ
Khi đó, như bạn nói, điều này gây ra sự cố mất hiệu lực bộ nhớ cache - mặc dù thực sự điều đó không phải là quan trọng ở hầu hết các nơi. Nhưng đối với điều này - các sự kiện redis (pub / sub) cho phép một cách dễ dàng để truyền phát các khóa đang thay đổi cho tất cả các nút, vì vậy họ có thể thả bản sao cục bộ của mình - nghĩa là:lần tới, chúng tôi sẽ lấy bản sao mới từ redis . Do đó, chúng tôi phát các tên khóa thay đổi so với một tên kênh sự kiện.
Công cụ:redis trên máy chủ ubuntu; BookSleeve như một trình bao bọc redis; protobuf-net và GZipStream (được bật / tắt tự động tùy thuộc vào kích thước) để đóng gói dữ liệu.
Vì vậy:các sự kiện redis pub / sub được sử dụng để làm mất hiệu lực bộ nhớ cache cho một khóa nhất định từ one nút (nút biết trạng thái đã thay đổi) ngay lập tức (khá nhiều) thành tất cả các nút.
Về các quy trình riêng biệt (từ các nhận xét, "bạn có sử dụng bất kỳ loại mô hình bộ nhớ dùng chung nào cho nhiều quy trình riêng biệt cung cấp cùng một dữ liệu không?"):Không, chúng tôi không làm điều đó. Mỗi hộp cấp web chỉ thực sự lưu trữ một quy trình (thuộc bất kỳ cấp nào đã cho), với nhiều lần thuê trong điều đó, vì vậy trong cùng một quy trình, chúng tôi có thể có 70 trang web. Vì các lý do cũ (tức là "nó hoạt động và không cần sửa"), chúng tôi chủ yếu sử dụng bộ đệm ẩn http với danh tính trang web như một phần của khóa.
Đối với một số bộ phận sử dụng nhiều dữ liệu lớn của hệ thống, chúng tôi có các cơ chế để duy trì trên đĩa để mô hình trong bộ nhớ có thể được chuyển giữa các miền ứng dụng kế tiếp khi web tái chế tự nhiên (hoặc được triển khai lại), nhưng đó là không liên quan đến redis.
Đây là một ví dụ có liên quan cho thấy chỉ hương vị rộng rãi về cách điều này có thể hoạt động - tìm một số trường hợp sau đây, rồi nhập một số tên chính vào:
static class Program
{
static void Main()
{
const string channelInvalidate = "cache/invalidate";
using(var pub = new RedisConnection("127.0.0.1"))
using(var sub = new RedisSubscriberConnection("127.0.0.1"))
{
pub.Open();
sub.Open();
sub.Subscribe(channelInvalidate, (channel, data) =>
{
string key = Encoding.UTF8.GetString(data);
Console.WriteLine("Invalidated {0}", key);
});
Console.WriteLine(
"Enter a key to invalidate, or an empty line to exit");
string line;
do
{
line = Console.ReadLine();
if(!string.IsNullOrEmpty(line))
{
pub.Publish(channelInvalidate, line);
}
} while (!string.IsNullOrEmpty(line));
}
}
}
Những gì bạn sẽ thấy là khi bạn nhập tên khóa, nó sẽ hiển thị ngay lập tức trong tất cả các phiên bản đang chạy, sau đó sẽ kết xuất bản sao cục bộ của khóa đó. Rõ ràng là trong thực tế sử dụng, hai kết nối sẽ cần phải được đặt ở đâu đó và giữ ở trạng thái mở, vì vậy sẽ không ở trong using
các câu lệnh. Chúng tôi sử dụng hầu như một phần tử duy nhất cho việc này.