1:chỉ có một kênh trong ví dụ của bạn (Test
); một kênh chỉ là tên được sử dụng cho một sàn giao dịch phụ / quán rượu cụ thể. Tuy nhiên, cần phải sử dụng 2 kết nối do các chi tiết cụ thể về cách hoạt động của API redis. Kết nối có bất kỳ đăng ký không thể làm bất cứ điều gì khác ngoại trừ:
- nghe tin nhắn
- quản lý các đăng ký của riêng mình (
subscribe
,psubscribe
,unsubscribe
,punsubscribe
)
Tuy nhiên, tôi không hiểu điều này:
private static Dictionary<string, RedisSubscriberConnection>
Bạn không nên cần nhiều hơn một kết nối thuê bao trừ khi bạn đang phục vụ cho một thứ gì đó dành riêng cho bạn. Một kết nối thuê bao duy nhất có thể xử lý một số lượng đăng ký tùy ý. Kiểm tra nhanh client list
trên một trong các máy chủ của tôi và tôi có một kết nối với (tại thời điểm viết bài) 23.002 đăng ký. Điều này có thể được giảm bớt, nhưng:nó hoạt động.
2:đăng ký mẫu hỗ trợ ký tự đại diện; vì vậy thay vì đăng ký /topic/1
, /topic/2/
vv bạn có thể đăng ký /topic/*
. Tên của thực tế kênh được publish
sử dụng được cung cấp cho người nhận như một phần của chữ ký gọi lại.
Hoặc có thể hoạt động. Cần lưu ý rằng hiệu suất của publish
bị ảnh hưởng bởi tổng số lượng đăng ký duy nhất - nhưng thành thật mà nói, nó vẫn nhanh một cách ngu ngốc (như trong:0ms) ngay cả khi bạn có hàng chục nghìn kênh đã đăng ký bằng cách sử dụng subscribe
thay vì psubscribe
.
Nhưng từ publish
Độ phức tạp về thời gian:O (N + M) trong đó N là số lượng khách hàng đã đăng ký kênh nhận và M là tổng số mẫu đã đăng ký (bởi bất kỳ khách hàng nào).
Tôi khuyên bạn nên đọc tài liệu redis của pub / sub.
Chỉnh sửa để theo dõi các câu hỏi:
a) Tôi cho rằng tôi sẽ phải "xuất bản" đồng bộ (sử dụng Kết quả hoặc Chờ ()) nếu tôi muốn đảm bảo thứ tự gửi các mục từ cùng một nhà xuất bản được giữ nguyên khi nhận các mục, đúng không?
điều đó sẽ không tạo ra sự khác biệt nào cả; vì bạn đề cập đến Result
/ Wait()
, Tôi giả sử bạn đang nói về BookSleeve - trong trường hợp đó, bộ ghép kênh đã bảo toàn lệnh. Bản thân Redis là một luồng đơn và sẽ luôn xử lý các lệnh trên một kết nối theo thứ tự. Tuy nhiên:các cuộc gọi lại trên thuê bao có thể được thực hiện không đồng bộ và có thể được chuyển (riêng) cho một chuỗi công nhân. Tôi hiện đang điều tra xem liệu tôi có thể buộc điều này theo thứ tự từ RedisSubscriberConnection
hay không .
Cập nhật:từ 1.3.22 trở đi, bạn có thể đặt CompletionMode
đến PreserveOrder
- sau đó tất cả các lệnh gọi lại sẽ được hoàn thành tuần tự thay vì đồng thời.
b) sau khi thực hiện các điều chỉnh theo đề xuất của bạn, tôi nhận được hiệu suất tuyệt vời khi xuất bản một số mục bất kể kích thước của trọng tải. Tuy nhiên, khi gửi 100.000 mục trở lên bởi cùng một nhà xuất bản, hiệu suất giảm nhanh chóng (chỉ còn 7-8 giây để gửi từ máy của tôi).
Thứ nhất, thời gian đó nghe có vẻ cao - tôi nhận được thử nghiệm cục bộ (cho 100.000 ấn phẩm, bao gồm cả việc chờ phản hồi cho tất cả chúng) 1766ms (cục bộ) hoặc 1219ms (từ xa) (nghe có vẻ hơi phản trực quan, nhưng "cục bộ" của tôi không phải là ' t đang chạy cùng một phiên bản redis; "điều khiển từ xa" của tôi là 2.6.12 trên Centos; "cục bộ" của tôi là 2.6.8-pre2 trên Windows).
Tôi không thể làm cho máy chủ thực tế của bạn nhanh hơn hoặc tăng tốc mạng, nhưng:trong trường hợp đây là phân mảnh gói, tôi đã thêm (chỉ dành cho bạn) một SuspendFlush()
/ ResumeFlush()
đôi. Điều này vô hiệu hóa háo hức xả (nghĩa là khi hàng đợi gửi trống; các loại xả khác vẫn xảy ra); bạn có thể thấy điều này hữu ích:
conn.SuspendFlush();
try {
// start lots of operations...
} finally {
conn.ResumeFlush();
}
Lưu ý rằng bạn không nên Wait
cho đến khi bạn tiếp tục, bởi vì cho đến khi bạn gọi ResumeFlush()
có thể có một số hoạt động vẫn còn trong bộ đệm gửi. Với tất cả những điều đó, tôi nhận được (cho 100.000 hoạt động):
local: 1766ms (eager-flush) vs 1554ms (suspend-flush)
remote: 1219ms (eager-flush) vs 796ms (suspend-flush)
Như bạn có thể thấy, nó giúp ích nhiều hơn cho các máy chủ từ xa, vì nó sẽ đưa ít gói tin hơn qua mạng.
Tôi không thể sử dụng các giao dịch bởi vì sau này các mục sắp xuất bản không phải tất cả đều có sẵn cùng một lúc. Có cách nào để tối ưu hóa kiến thức đó không?
Tôi nghĩ rằng điều đó được giải quyết bằng cách ở trên - nhưng lưu ý rằng gần đây CreateBatch
cũng đã được thêm vào. Một lô hoạt động giống như một giao dịch - chỉ là:không có giao dịch. Một lần nữa, nó là một cơ chế khác để giảm phân mảnh gói tin. Trong trường hợp cụ thể của bạn, tôi nghi ngờ việc tạm ngừng / tiếp tục (ngay lập tức) là lựa chọn tốt nhất của bạn.
Bạn có khuyên bạn nên có một RedisConnection chung và một RedisSubscriberConnection hoặc bất kỳ cấu hình nào khác để trình bao bọc đó thực hiện các chức năng mong muốn không?
Miễn là bạn không thực hiện các thao tác chặn (blpop
, brpop
, brpoplpush
vv), hoặc đặt các BLOB quá khổ xuống dây (có khả năng làm trì hoãn các hoạt động khác trong khi nó rõ ràng), khi đó một kết nối duy nhất của mỗi loại thường hoạt động khá tốt. Nhưng YMMV tùy thuộc vào yêu cầu sử dụng chính xác của bạn.