Memcached的另類用途 - Rate Limit

我們通常用memcached來做緩存來提高系統性能,其實它不僅僅是一個緩存工具,我們還可以用它來做其他用途,比如下列常見的需求:
1. 避免服務器的負擔太大,限制Open [url=http://www.iteye.com/wiki/JavaEye/1499-javaeye-api-help]API[/url]的調用次數
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做緩存之外的用途嗎?歡迎交流。

延伸閱讀:[url=http://simonwillison.net/2009/Jan/7/ratelimitcache/]Python的實現[/url]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章