Cài đặt Redis server phục vụ cho nhiều ứng dụng cùng một lúc

image source: https://architecturenotes.co/redis/

Tiền đề

Khi một instance Redis được khai thác bởi nhiều application cùng một lúc, vấn đề xung đột key có thể xảy ra, khi có hai application đọc ghi trên cùng một khóa. Vấn đề này có một số phương án giải quyết khác nhau:

  1. Sử dụng key prefix: cấu hình mỗi ứng dụng đặt tên cho các key với những tiền tố khác nhau
  2. Sử dụng redis database: mặc định, mỗi instance redis cho phép khai thác với 16 database khác nhau (có thể tăng thêm), được đánh số từ 0-15. Hầu hết các redis client đều cho phép cấu hình ứng dụng sử dụng database index nào. Nếu không chỉ định, client sẽ sử dụng database số 0.
  3. Cài đặt nhiều instance Redis trên cùng một máy chủ, mỗi instance hoạt động trên một port khác nhau.

Hai phương án đầu tiên có thể hữu dụng trong giai đoạn development, tuy nhiên không thích hợp cho production. Lý do là bởi mục tiêu của Redis là đóng vai trò một hệ cơ sở dữ liệu key-value tốc độ siêu cao, hệ quả là Redis được thiết kế đơn luồng: mỗi instance Redis hoạt động trên chỉ một thread duy nhất để không phải tốn chi phí thời gian cho việc CPU chuyển đổi ngữ cảnh giữa các thread. Khi nhiều ứng dụng cùng khai thác một instance Redis, một phiên đọc ghi của ứng dụng này sẽ block hoạt động của ứng dụng khác. Chi phí thời gian là rất đắt đỏ.

Phương án số 3 cho phép các intance của Redis hoạt động trên các core khác nhau của CPU và là giải pháp tối ưu hơn, và là tiêu điểm của bài viết này.

Các script ví dụ trong bài viết này được viết ra cho máy chủ Ubuntu 16.04. Chúng có thể được sử dụng tốt cho hầu hết các máy chủ Debian base và sử dụng systemd.

Cài đặt Redis package

sudo apt update
sudo apt install redis-server
sudo netstat -lnp | grep redis # kiểm tra
redis-cli PING # xac nhan
redis-cli monitor # theo doi # theo dõi

Cấu hình supervise

Lựa chọn hệ init system nào sẽ được dùng để khởi động Redis khi máy chủ được boot. Ở đây chọn systemd.

sudo -u redis vim /etc/redis/redis.conf

Tìm đến dòng supervised no và đặt thành supervised systemd. Hoặc sử dụng câu lệnh:

sudo -u redis sed -i -e 's@^supervised no@supervised systemd@' /etc/redis/redis.conf

Clone Redis config cho instance mới

Tham khảo thêm tại tập tin /lib/systemd/system/redis-server@.service.

Copy một file config mới:

sudo cp /etc/redis/redis.conf /etc/redis/redis-6379.conf
sudo chown redis:redis /etc/redis/redis-6379.conf

Chỉnh sửa tập tin mới tạo ra, thay đổi dbfilename thành dump-%port.rdb, trong đó %port là port được sử dụng cho instance mới,hoặc sử dụng câu lệnh:

sudo -u redis sed -i -e 's@^dbfilename .*@dbfilename dump-6379.rdb@' /etc/redis/redis-6379.conf

Thay đổi port:

sudo -u redis sed -i -e 's@^port .*@port 6379@' /etc/redis/redis-6379.conf

Thay đổi unixsocket:

sudo -u redis sed -i -e 's@^\(# \)\{0,1\}unixsocket .*@unixsocket /var/run/redis-6379/redis-server.sock@' /etc/redis/redis-6379.conf

Thay đổi cấu hình tập tin log:

sudo -u redis sed -i -e 's@^logfile .*@logfile /var/log/redis/redis-server-6379.log@' /etc/redis/redis-6379.conf

Thay đổi pidfile:

sudo -u redis sed -i -e 's@^pidfile .*@pidfile /run/redis-6379/redis-server.pid@' /etc/redis/redis-6379.conf

Lưu ý kiểm tra tập tin sau khi hoàn thành.

Cấu hình daemon cho instance mới

Clone một tập tin khai báo service mới:

sudo cp /lib/systemd/system/redis-server@.service /lib/systemd/system/redis-server@6379.service

Sau đó thay thế tất cả các placeholder với nội dung %i trong file service thành port mong muốn.

Hoặc kết hợp cả hai bước trên bằng câu lệnh:

sudo sh -c  "sed 's/%i/6379/g' /lib/systemd/system/redis-server@.service > /lib/systemd/system/redis-server@6379.service"

Lưu ý kiểm tra tập tin sau khi hoàn thành.

Khởi động instance

Khởi động daemon cho instance mới bằng câu lệnh:

sudo systemctl start redis-server@6379.service

Kiểm tra trạng thái:

systemctl status redis-server@myname.service
sudo netstat -lnp | grep redis
redis-cli -s /var/run/redis-myname/redis-server.sock info | grep config_file

Nếu mọi chuyện đều ổn, ta đăng ký service:

systemctl enable redis-server@6379.service

Đặt mật khẩu cho instance

Sử dụng ACL GENPASS, random.org, hay bất kỳ chuỗi string ngẫu nhiên nào đủ dài (tối thiểu ~100 ký tự). Do bản chất tốc độ quá cao, một instance Redis có thể xác thực rất nhiều mật khẩu trong một thời gian rất ngắn, một mật khẩu ngắn sẽ vô dụng. Lưu ý là Redis cap password length tại 512 ký tự.

Thay đổi mật khẩu tại dòng requirepass của file config, hoặc sử dụng câu lệnh:

sudo -u redis sed -i -e 's@^\(# \)\{0,1\}requirepass .*@requirepass xxxxxxx@' /etc/redis/redis-6379.conf

Sau đó khởi động lại daemon:

sudo systemctl restart  redis-server@63790.service

Wrap up

Tất cả các bước thực hiện trên có thể tóm gọn trong các script dưới đây, lưu ý thay thế 6379secret thành portpassword mong muốn:

sudo echo
sudo cp /etc/redis/redis.conf /etc/redis/redis-6379.conf
sudo sed -i -e 's@^supervised no@supervised systemd@' /etc/redis/redis-6379.conf
sudo sed -i -e 's@^dbfilename .*@dbfilename dump-6379.rdb@' /etc/redis/redis-6379.conf
sudo sed -i -e 's@^port .*@port 6379@' /etc/redis/redis-6379.conf
sudo sed -i -e 's@^\(# \)\{0,1\}unixsocket .*@unixsocket /var/run/redis-6379/redis-server.sock@' /etc/redis/redis-6379.conf
sudo sed -i -e 's@^logfile .*@logfile /var/log/redis/redis-server-6379.log@' /etc/redis/redis-6379.conf
sudo sed -i -e 's@^pidfile .*@pidfile /run/redis-6379/redis-server.pid@' /etc/redis/redis-6379.conf
sudo sed -i -e 's@^\(# \)\{0,1\}requirepass .*@requirepass super-long-secret-password@' /etc/redis/redis-6379.conf
sudo chown redis:redis /etc/redis/redis-6379.conf
sudo sh -c  "sed 's/%i/6379/g' /lib/systemd/system/redis-server@.service > /lib/systemd/system/redis-server@6379.service"
sudo systemctl start redis-server@6379.service
sudo systemctl enable redis-server@6379.service

Để kiểm tra:

redis-cli -p 6379 -a password PING # xac nhan
redis-cli -p 6379 -a password monitor # theo doi # theo dõi

Gỡ bỏ instance

sudo systemctl stop redis-server@6379.service
sudo systemctl disable redis-server@6379.service
sudo netstat -lnp | grep redis # kiểm tra
sudo rm /lib/systemd/system/redis-server@6379.service
sudo rm /etc/redis/redis-6379.conf

Redis in Docker

Một điều cần lưu ý là Rind bị sụt giảm hiệu năng khá nhiều so với native, điều này đặc biệt nghiêm trọng bởi Redis có nhu cầu trả lời mọi request trong đơn vị đo mili-giây. Nguyên nhân sụt giảm tới phần lới tới từ các lớp ảo hóa network. Kết nối container vào network host có thể khắc phục một phần vấn đề này.

Loading

Leave a Reply

Your email address will not be published. Required fields are marked *