Memcached的另类用途 - Rate Limit

我们通常用memcached来做缓存来提高系统性能,其实它不仅仅是一个缓存工具,我们还可以用它来做其他用途,比如下列常见的需求:
1. 避免服务器的负担太大,限制Open API的调用次数
2. 避免恶意尝试密码,限制登录错误次数

这2个需求的共同特点是要能够统计在某个时间段内,某个操作被执行了多少次,利用memcached的失效时间和它的incr指令,可以很方便地实现,直接上代码:
module RateLimit
  class OverRateLimitError < StandardError; end

  def over_limit?(key, options, &block)
    requests = Rails.cache.increment("RateLimit/#{key}")
    if requests.nil?
      Rails.cache.write("RateLimit/#{key}", 1, :expires_in => options[:per].minutes)
      requests = 1
    end
    if requests > options[:requests]
      raise OverRateLimitError.new
    else
      block.call
    end
  end

  def reset_limit(key)
    key.gsub!(/\s/, '')
    Rails.cache.delete("RateLimit/#{key}")
  end
end

Rails.cache是rails带的一个memcached封装,你也可以直接用memcached client自己来写。

使用这个代码很容易,以需求1为例子,我们可以include这个module,然后在需要统计的某个api调用(可用around_filter将这个代码简化):
      begin
        #每小时不能超过360次api调用
        over_limit?("Api/#{key}", :per => 60, :requests => 360) {
          #真正的api代码段
        }
      rescue OverRateLimitError
        render :text => "error.api.over.limit", :status => 400 and return false
      end

这里的key,你可以根据客户端ip+api名称或者授予客户端的key来生成。

你也在用memcached做缓存之外的用途吗?欢迎交流。

延伸阅读: Python的实现

你可能感兴趣的:(memcached,Ruby,Rails,360,rack)