CẬP NHẬT: bên dưới áp dụng cho các phiên bản Redis lên đến 3.2. Từ phiên bản đó, sao chép dựa trên hiệu ứng dỡ bỏ lệnh cấm đối với thuyết không xác định, do đó tất cả các cược bị tắt (hay đúng hơn là vào).
Bạn không thể (và không nên) trộn SCAN
họ lệnh với bất kỳ lệnh ghi nào trong một tập lệnh bởi vì câu trả lời của câu trả lời trước đây phụ thuộc vào cấu trúc dữ liệu Redis nội bộ, đến lượt nó, là duy nhất cho quy trình máy chủ. Nói cách khác, hai quy trình Redis (ví dụ:chính và phụ) không được đảm bảo trả lại các câu trả lời giống nhau (vì vậy trong ngữ cảnh sao chép Redis [không phải hoạt động - mà dựa trên câu lệnh] sẽ phá vỡ nó).
Redis cố gắng tự bảo vệ mình khỏi những trường hợp như vậy bằng cách chặn bất kỳ lệnh ghi nào (chẳng hạn như DEL
) nếu nó được thực thi sau một lệnh ngẫu nhiên (ví dụ:SCAN
mà còn TIME
, SRANDMEMBER
và tương tự). Tôi chắc rằng có nhiều cách để giải quyết vấn đề đó, nhưng bạn có muốn làm điều đó không? Hãy nhớ rằng, bạn sẽ đi vào lãnh thổ không xác định, nơi hành vi của hệ thống không được xác định.
Thay vào đó, hãy chấp nhận thực tế rằng bạn không nên kết hợp các lần đọc và ghi ngẫu nhiên và cố gắng nghĩ ra một cách tiếp cận khác để giải quyết vấn đề của bạn, cụ thể là xóa một loạt các khóa theo một mẫu một cách nguyên tử.
Trước tiên, hãy tự hỏi bản thân xem bạn có thể nới lỏng bất kỳ yêu cầu nào không. Nó có phải là nguyên tử không? Tính nguyên tử có nghĩa là Redis sẽ bị chặn trong suốt thời gian xóa (bất kể lần thực hiện cuối cùng) và thời lượng của hoạt động phụ thuộc vào quy mô của công việc (tức là số lượng khóa bị xóa và nội dung của chúng [xóa một tập hợp lớn là đắt hơn việc xóa một chuỗi ngắn chẳng hạn]).
Nếu tính nguyên tử không phải là bắt buộc, hãy định kỳ / lười biếng SCAN
và xóa theo lô nhỏ. Nếu đó là điều bắt buộc, hãy hiểu rằng về cơ bản bạn đang cố gắng mô phỏng ác KEYS
lệnh :) Nhưng bạn có thể làm tốt hơn nếu bạn có kiến thức trước về mẫu.
Giả sử mẫu được biết trong thời gian chạy ứng dụng của bạn, bạn có thể thu thập các khóa liên quan (ví dụ:trong một Tập hợp) và sau đó sử dụng bộ sưu tập đó để thực hiện xóa theo cách nguyên tử và an toàn sao chép, hiệu quả hơn so với việc sử dụng toàn bộ không gian phím .
Tuy nhiên, vấn đề "khó" nhất là bạn có cần chạy đối sánh mẫu đặc biệt mà vẫn đảm bảo tính nguyên tử hay không. Nếu vậy, vấn đề chỉ nằm ở chỗ có được ảnh chụp nhanh được lọc theo mẫu của không gian phím ngay sau đó là một loạt các lần xóa (nhấn mạnh lại:trong khi cơ sở dữ liệu bị chặn). Trong trường hợp đó, bạn rất có thể sử dụng KEYS
trong tập lệnh Lua của bạn và hy vọng điều tốt nhất ... (nhưng biết rõ rằng bạn có thể sử dụng SHUTDOWN NOSAVE
khá nhanh:P).
Tối ưu hóa cuối cùng là lập chỉ mục chính không gian khóa. Cả SCAN
và KEYS
về cơ bản là quét toàn bộ bảng, vậy nếu chúng ta lập chỉ mục bảng đó thì sao? Hãy tưởng tượng việc giữ một chỉ mục trên tên của các khóa có thể được truy vấn trong một giao dịch - bạn có thể có thể sử dụng Tập hợp được sắp xếp và phạm vi từ vựng (HT @TwBert ) để loại bỏ hầu hết các nhu cầu đối sánh mẫu. Nhưng với một chi phí đáng kể ... bạn sẽ không chỉ thực hiện việc ghi sổ kế toán kép (lưu trữ chi phí tên của mỗi khóa trong RAM và CPU), bạn sẽ buộc phải tăng thêm độ phức tạp cho ứng dụng của mình. Tại sao lại thêm phức tạp? Bởi vì để triển khai một chỉ mục như vậy, bạn phải tự duy trì nó trong lớp ứng dụng (và có thể là tất cả các tập lệnh Lua khác của bạn), nên cẩn thận gói từng thao tác ghi vào Redis trong một giao dịch cũng cập nhật chỉ mục.
Giả sử bạn đã làm tất cả những điều đó (và có tính đến những cạm bẫy rõ ràng như khả năng xảy ra lỗi phức tạp hơn, ít nhất là tăng gấp đôi tải ghi trên Redis, RAM &CPU, hạn chế về tỷ lệ mở rộng, v.v.), bạn có thể tự vỗ về và tự chúc mừng vì đã sử dụng Redis theo cách mà nó không được thiết kế cho. Mặc dù các phiên bản sắp tới của Redis có thể (hoặc có thể không) bao gồm các giải pháp tốt hơn cho thử thách này ( @TwBert - bạn muốn thực hiện một RCP / đóng góp chung và lại hack Redis một chút? ), trước khi thử điều này, tôi thực sự khuyên bạn nên suy nghĩ lại các yêu cầu ban đầu và xác minh rằng bạn đang sử dụng Redis đúng cách (tức là thiết kế "lược đồ" theo nhu cầu truy cập dữ liệu của bạn).