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