Chúng tôi đã có một tình huống mà tôi phải đối phó với một lượng lớn các sự kiện đến máy chủ của chúng tôi, trung bình khoảng 1000 sự kiện mỗi giây (cao điểm có thể là ~ 2000).
Vấn đề
Hệ thống của chúng tôi được lưu trữ trên Heroku và sử dụng DB Heroku Postgres tương đối đắt tiền , cho phép tối đa 500 kết nối DB. Chúng tôi sử dụng nhóm kết nối để kết nối từ máy chủ đến DB.
Các sự kiện đến nhanh hơn nhóm kết nối DB có thể xử lý
Vấn đề chúng ta gặp phải là các sự kiện đến nhanh hơn nhóm kết nối có thể xử lý. Vào thời điểm một kết nối đã kết thúc vòng kết nối mạng từ máy chủ đến DB, do đó, nó có thể được giải phóng trở lại nhóm, nhiều hơn n
các sự kiện bổ sung được đưa vào.
Cuối cùng, các sự kiện xếp chồng lên nhau, chờ đợi để được lưu và vì không có kết nối có sẵn trong nhóm, chúng hết thời gian và toàn bộ hệ thống được hiển thị không hoạt động.
Chúng tôi đã giải quyết tình huống khẩn cấp bằng cách phát ra các sự kiện tần số cao vi phạm với tốc độ chậm hơn từ khách hàng, nhưng chúng tôi vẫn muốn biết cách xử lý tình huống này trong trường hợp chúng tôi cần xử lý các sự kiện tần số cao đó.
Những ràng buộc
Các khách hàng khác có thể muốn đọc các sự kiện đồng thời
Các máy khách khác liên tục yêu cầu đọc tất cả các sự kiện bằng một khóa cụ thể, ngay cả khi chúng chưa được lưu trong DB.
Một khách hàng có thể truy vấn GET api/v1/events?clientId=1
và nhận tất cả các sự kiện được gửi bởi khách hàng 1, ngay cả khi những sự kiện đó chưa được thực hiện lưu trong DB.
Có bất kỳ ví dụ "lớp học" nào về cách giải quyết vấn đề này không?
Phương pháp khả thi
Ghi danh các sự kiện trên máy chủ của chúng tôi
Chúng ta có thể liệt kê các sự kiện trên máy chủ (với hàng đợi có đồng thời tối đa là 400 để nhóm kết nối không hết).
Đây là ý tưởng tồi vì:
- Nó sẽ ăn hết bộ nhớ máy chủ có sẵn. Các sự kiện được xếp chồng lên nhau sẽ tiêu tốn một lượng lớn RAM.
- Máy chủ của chúng tôi khởi động lại cứ sau 24 giờ . Đây là một giới hạn cứng được áp đặt bởi Heroku. Máy chủ có thể khởi động lại trong khi các sự kiện được xử lý khiến chúng ta mất các sự kiện bị mê hoặc.
- Nó giới thiệu trạng thái trên máy chủ, do đó làm tổn thương khả năng mở rộng. Nếu chúng tôi có thiết lập nhiều máy chủ và khách hàng muốn đọc tất cả các sự kiện đã lưu + đã lưu, chúng tôi sẽ không biết máy chủ nào có các sự kiện được yêu thích trực tiếp.
Sử dụng một hàng đợi tin nhắn riêng
Tôi giả sử chúng ta có thể sử dụng một hàng đợi tin nhắn, (như RabbitMQ ?), Nơi chúng ta bơm các tin nhắn trong đó và ở đầu bên kia có một máy chủ khác chỉ liên quan đến việc lưu các sự kiện trên DB.
Tôi không chắc rằng hàng đợi tin nhắn có cho phép truy vấn các sự kiện đã được xử lý hay không (vì vậy vẫn chưa được lưu) vì vậy nếu một khách hàng khác muốn đọc tin nhắn của một khách hàng khác, tôi có thể nhận các tin nhắn đã lưu từ DB và các tin nhắn đang chờ xử lý từ hàng đợi và ghép chúng lại với nhau để tôi có thể gửi chúng trở lại máy khách yêu cầu đọc.
Sử dụng nhiều cơ sở dữ liệu, mỗi cơ sở lưu một phần thông điệp với máy chủ điều phối DB trung tâm để quản lý chúng
Một giải pháp khác chúng tôi mặc dù là sử dụng nhiều cơ sở dữ liệu, với một "bộ điều phối DB / bộ cân bằng tải" trung tâm. Khi nhận được một sự kiện, điều phối viên này sẽ chọn một trong các cơ sở dữ liệu để viết tin nhắn. Điều này sẽ cho phép chúng tôi sử dụng nhiều cơ sở dữ liệu Heroku, do đó tăng giới hạn kết nối lên 500 x số lượng cơ sở dữ liệu.
Khi truy vấn đọc, điều phối viên này có thể đưa ra SELECT
các truy vấn cho từng cơ sở dữ liệu, hợp nhất tất cả các kết quả và gửi lại cho khách hàng đã yêu cầu đọc.
Đây là ý tưởng tồi vì:
- Ý tưởng này nghe có vẻ như ... ahem .. quá kỹ thuật? Sẽ là một cơn ác mộng để quản lý là tốt (sao lưu, vv ..). Việc xây dựng và bảo trì rất phức tạp và trừ khi thực sự cần thiết, nó có vẻ như là vi phạm KISS .
- Nó hy sinh tính nhất quán . Thực hiện các giao dịch trên nhiều DB là điều không nên nếu chúng ta thực hiện ý tưởng này.
ANALYZE
các truy vấn và chúng không phải là vấn đề. Tôi cũng đã xây dựng một nguyên mẫu để kiểm tra giả thuyết nhóm kết nối và xác minh rằng đây thực sự là vấn đề. Cơ sở dữ liệu và máy chủ tự sống trên các máy khác nhau do đó độ trễ. Ngoài ra, chúng tôi không muốn từ bỏ Heroku trừ khi thực sự cần thiết, không lo lắng về việc triển khai là một điểm cộng rất lớn cho chúng tôi.
select null
trên 500 kết nối. Tôi cá là bạn sẽ thấy rằng nhóm kết nối không phải là vấn đề ở đó.