Bỏ qua, đến nội dung

Hướng dẫn cài đặt — Worker ID Allocator Redis

Yêu cầu

Thành phầnYêu cầu
Digiforce ServerĐang chạy trong chế độ cluster (nhiều instance)
RedisĐang hoạt động và có thể kết nối từ tất cả instance

Khi nào cần plugin này?

Plugin cần thiết khi:

  • Chạy nhiều instance Digiforce cùng lúc (cluster/scaling)
  • Cần Snowflake ID không trùng lặp giữa các instance
  • Dùng Docker/Kubernetes để deploy

Không cần khi chỉ chạy 1 instance — allocator mặc định (in-memory) đủ dùng.

Bước 1: Đảm bảo Redis đã cấu hình

Plugin sử dụng Redis qua app.redisConnectionManager — cần đảm bảo Redis đã được cấu hình cho ứng dụng:

bash
# .env
REDIS_URL=redis://localhost:6379

Hoặc với authentication:

bash
REDIS_URL=redis://:password@redis-host:6379/0

Bước 2: Kích hoạt plugin

Vào Settings → Plugin Manager, tìm plugin-workerid-allocator-redis và bật.

Hoặc kích hoạt qua dòng lệnh:

bash
yarn pm enable plugin-workerid-allocator-redis

Khi kích hoạt, plugin đăng ký adapter trong event beforeLoad:

typescript
app.workerIdAllocator.setAdapter(new WorkerIdAllocator(app));

Bước 3: Kiểm tra

Khởi động server và kiểm tra log:

[info] worker id manager initialized with identifier: 192.168.1.100
[info] Allocated worker ID: 0

Kiểm tra Redis keys

bash
redis-cli
> KEYS snowflake:worker:*
1) "snowflake:worker:main:0"

> GET snowflake:worker:main:0
"192.168.1.100"

> TTL snowflake:worker:main:0
(integer) 118

Chi tiết kỹ thuật

Identifier

Plugin tự xác định identifier cho instance theo thứ tự ưu tiên:

Ưu tiênNguồnKhi nào dùng
1process.env.POD_IPKubernetes — IP của pod
2Local IP (non-container)Máy vật lý hoặc VM
3process.env.HOSTNAME hoặc os.hostname()Container Docker

Cơ chế cấp phát

Plugin duyệt từ ID 0 đến 31, dùng SET ... NX EX (atomic) để thử chiếm:

SET snowflake:worker:main:0 192.168.1.100 EX 120 NX
  • NX = chỉ set nếu key chưa tồn tại
  • EX 120 = key tự hết hạn sau 120 giây

Nếu ID 0 đã bị chiếm, thử 1, 2... cho đến khi thành công.

Cơ chế gia hạn (Renewal)

Mỗi 60 giây, plugin chạy Lua script atomic:

lua
if redis.call('GET', KEYS[1]) == ARGV[1] then
  return redis.call('EXPIRE', KEYS[1], ARGV[2])
else
  return 0
end

Script kiểm tra identifier trước khi gia hạn — tránh gia hạn key của instance khác.

Nếu gia hạn thất bại, plugin retry tối đa 3 lần.

Cơ chế giải phóng (Release)

Khi instance shutdown gracefully, plugin xóa key bằng Lua script tương tự:

lua
if redis.call('GET', KEYS[1]) == ARGV[1] then
  return redis.call('DEL', KEYS[1])
else
  return 0
end

Nếu instance crash (không shutdown gracefully), key tự hết hạn sau 120 giây.

Fallback khi không có Redis

Nếu không kết nối được Redis, plugin trả về random ID (0-31):

typescript
return Math.floor(Math.random() * 32);

Cảnh báo

Random ID có thể trùng lặp! Fallback chỉ để tránh crash — không nên dùng trong production mà không có Redis.

Triển khai trên Kubernetes

Đặt biến môi trường POD_IP trong deployment:

yaml
spec:
  containers:
    - name: digiforce
      env:
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP

Plugin sẽ dùng POD_IP làm identifier, đảm bảo mỗi pod có identifier duy nhất.

Lưu ý quan trọng

  • Tối đa 32 instance (maxWorkerId = 31) — đủ cho hầu hết cluster
  • Nếu tất cả 32 ID đều bị chiếm, plugin throw Error — instance không khởi động được
  • Lease TTL 120 giây > Renewal interval 60 giây — đảm bảo không bị mất lease giữa 2 lần gia hạn
  • Redis cần uptime cao — mất Redis không ảnh hưởng instance đang chạy (vẫn giữ ID), nhưng instance mới không cấp phát được