我们通常用memcached来做缓存来提高系统性能,其实它不仅仅是一个缓存工具,我们还可以用它来做其他用途,比如下列常见的需求:
1. 避免服务器的负担太大,限制Open [url=http://www.iteye.com/wiki/JavaEye/1499-javaeye-api-help]API[/url]的调用次数
2. 避免恶意尝试密码,限制登录错误次数
这2个需求的共同特点是要能够统计在某个时间段内,某个操作被执行了多少次,利用memcached的失效时间和它的incr指令,可以很方便地实现,直接上代码:
Rails.cache是rails带的一个memcached封装,你也可以直接用memcached client自己来写。
使用这个代码很容易,以需求1为例子,我们可以include这个module,然后在需要统计的某个api调用(可用around_filter将这个代码简化):
这里的key,你可以根据客户端ip+api名称或者授予客户端的key来生成。
你也在用memcached做缓存之外的用途吗?欢迎交流。
延伸阅读:[url=http://simonwillison.net/2009/Jan/7/ratelimitcache/]Python的实现[/url]
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]