nikotung / daily-git

daily records
0 stars 0 forks source link

A redis base ratelimiter #2

Open nikotung opened 3 years ago

nikotung commented 3 years ago

Rate limiter implemented by redis, from here

The operation serials are :

    ['zremrangebyscore', key, 0, start],
    ['zcard', key],
    ['zadd', key, now, now],
    ['zrange', key, 0, 0],
    ['zrange', key, -max, -max],
    ['zremrangebyrank', key, 0, -(max + 1)],
    ['pexpire', key, duration],
nikotung commented 3 years ago

在redis 中的存储是放在一个 sorted set 中,其中的member 和 score 都是请求进来时的时间戳.

nikotung commented 3 years ago

上述的几个步骤其实是放在pipeline 中操作的,保持原子性.

  db.multi(operations)
.exec(function (err, res) {
  if (err) return fn(err);

  var isIoRedis = Array.isArray(res[0]);
  var count = parseInt(isIoRedis ? res[1][1] : res[1]);
  var oldest = parseInt(isIoRedis ? res[3][1] : res[3]);
  var oldestInRange = parseInt(isIoRedis ? res[4][1] : res[4]);
  var resetMicro = (Number.isNaN(oldestInRange) ? oldest : oldestInRange) + duration * 1000;

  fn(null, {
    remaining: count < max ? max - count : 0,
    reset: Math.floor(resetMicro / 1000000),
    resetMs: Math.floor(resetMicro / 1000),
    total: max
  });
});
nikotung commented 3 years ago

Reference