0

Một số tip trick khi làm việc với Sidekiq

Nếu là một ROR developer thì chắc chắn bạn đã quá quen thuộc với Sidekiq. Dưới đây là một số tip trick khi làm việc với Sidekiq.

Sử dụng một initializer để tách riêng rdb

Redis mặc định số lượng db là 16(0~15). Mặc định, Sidekiq sử dụng db 0. Job sẽ bị conflict nếu như 2 hoặc nhiều project sử dụng Side trên cùng 1 DB. Mặc dù chúng có thể không gây ra lỗi hoặc exception nhưng nó có thể khiến mọi thứ bị chậm đi nếu có quá nhiều job không liên quan.

Để tránh việc bạn quên ko tách riêng db khi triển khai dự án, bạn nên cài đặt DB URL ngay sau khi cài đặt Sidekiq.

Điều cần lưu ý nhất khi cấu hình Redis là bạn phải định nghĩa 2 block Sidekiq.configure_server và Sidekiq.configure_client. Hãy đặt config này trong file config/initializers/sidekiq.rb của bạn:

Sidekiq.configure_server do |config|
  config.redis = { url: 'redis://redis.example.com:7372/0' }
end

Sidekiq.configure_client do |config|
  config.redis = { url: 'redis://redis.example.com:7372/0' }
end

Lưu ý: Với ví dụ trên hãy chắc chắn rằng không có hệ thống nào dùng db 0 cho Sidekiq.

Không sử dụng namespace của redis để tách riêng rdb

Không nên sử dụng namespace không chỉ với mỗi Sidekiq mà cả khi bạn dùng Redis cho mục đích nào khác. Điều quan trọng là namespace làm tăng kích cỡ mỗi khóa của bạn. Điều này được khuyến cáo bởi chính tác giả của Redis, bạn có thể đọc thêm ở đây (http://www.mikeperham.com/2015/09/24/storing-data-with-redis/)

Set pool: 25 trong file database.yml

Mặc định, một process Sidekiq tạo ra 25 thread. Nếu bạn không set pool: 25 trong database.yml trên production thì nó sẽ gây ra nhiều vấn đề khi số lượng job trên lên rất lớn.

Tác giả của Sidekiq cũng khuyến cáo không nên set số concurrency cao hơn 50.

Threading

Sidekiq là multithreaded vì vậy các worker của bạn cũng phải là thread-safe. Lưu ý là chỉ sử dụng các thread-safe library. Phần lớn các gem của ruby là thread-safe nhưng cũng có một số ngoại lệ như: right_aws, aws-s3, basecamp, therubyrace.

Ngoài ra một số gem cũng có thể gặp vấn đề là typhoeus, pg (postgres driver, hãy chắc chắn PG::Connection.isthreadsafe trả về true), RMagick (hãy thử dùng mini_magick thay thế), libxml-ruby...

Luôn viết thread-safe code (thông thường code bạn viết chính là thread-safe code) và không bao giờ sử dụng module Timeout(bạn có thể tìm hiểu thêm ở đây http://www.mikeperham.com/2015/05/08/timeout-rubys-most-dangerous-api/).

Không sử dụng Sidekiq cho những công việc quá dài

Bạn không nên sử dụng sidekiq với các tác vụ quá dài (trừ khi bạn sử dụng sidekiq cho việc giảm thời gian load của controller). Hãy duy trì job của bạn vừa phải, nếu bạn có một job thực hiện một vòng lặp qua một số lượng rất lớn các item, với mỗi item lại thực hiện một cơ số các thao tác thì tốc độ sẽ bị giảm đi khác nhiều, thay vào đó bạn có thể phân chia công việc đó ra bằng các job nhỏ hơn.

Truyền id của instance thay vì chính instance

Nên dùng SomeWorker.perform_later(user_id) thay vì SomeWorker.perform_later(user).

def perform(user_id)
  user = user.find(user_id)
  do_something(user) if user
end   

Điều này giúp bạn có thể kiểm tra xem instance còn tồn tại hay không trước khi thực hiện. Ví dụ bank có worker như sau: SomeWorker.set(wait_until: Time.current 3.days).perform_later(user) và đến thời điểm thực hiện thì user có thể đã không còn tồn tại nữa. Và nếu bạn set retry cho worker thì bạn đã có 1 vòng lặp vô nghĩa.

Stringify params

Một trong những lý do nữa mà bạn nên truyền Id là Redis DB size sẽ được giảm đi sơ với khi truyền instance. Sidekiq client API dùng JSON.dump để gửi dữ liệu vào Redis. Sidekiq server sẽ pull JSON data từ Redis và dùng JSON.load để convert dữ liệu thành kiểu dữ liệu của Ruby rồi truyền vào method perform. Không nên truyền symbol, tham số được đặt tên hoặc các object phứ tạp như Date hoặc Time vì những thứ đó sẽ không còn chính xác sau quá trình dump/load.

Xử lý deadlock

Do Sidekiq xử lý công việc đồng thời nên khả năng xảy ra deadlock là rất lớn.

Với Rails bạn có thể xử lý việc này 1 cách đơn giản.

  ad.with_lock do
    ad.send(action)
    ad.do_someting
  end

Tài liệu tham khảo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí