Memcached笔记——(四)应对高并发攻击【转】
http://snowolf.iteye.com/blog/1677495
近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源。他们的最好成绩,1秒钟可以并发6次,赶在Database入库前,Cache进行Missing Loading前,强占这其中十几毫秒的时间,进行恶意攻击。
相关链接:
Memcached笔记——(一)安装&常规错误&监控
Memcached笔记——(二)XMemcached&Spring集成
Memcached笔记——(三)Memcached使用总结
为了应对上述情况,做了如下调整:
- 更新数据时,先写Cache,然后写Database(双写),如果可以,写操作交给队列后续完成。
- 限制统一帐号,同一动作,同一秒钟并发次数,超过1次不做做动作,返回操作失败。
- 限制统一用户,每日动作次数,超限返回操作失败。
要完成上述操作,同事给我支招。用Memcached的add方法,就可以很快速的解决问题。不需要很繁琐的开发,也不需要依赖数据库记录,完全内存操作。![]()
以下实现一个判定冲突的方法:
- /**
- * 冲突延时 1秒
- */
- public static final int MUTEX_EXP = 1;
- /**
- * 冲突键
- */
- public static final String MUTEX_KEY_PREFIX = "MUTEX_";
- /**
- * 冲突判定
- *
- * @param key
- */
- public boolean isMutex(String key) {
- return isMutex(key, MUTEX_EXP);
- }
- /**
- * 冲突判定
- *
- * @param key
- * @param exp
- * @return true 冲突
- */
- public boolean isMutex(String key, int exp) {
- boolean status = true;
- try {
- if (memcachedClient.add(MUTEX_KEY_PREFIX + key, exp, "true")) {
- status = false;
- }
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- }
- return status;
- }
做个说明:
| 选项 | 说明 |
| add | 仅当存储空间中不存在键相同的数据时才保存 |
| replace | 仅当存储空间中存在键相同的数据时才保存 |
| set | 与add和replace不同,无论何时都保存 |
也就是说,如果add操作返回为true,则认为当前不冲突!![]()
回归场景,恶意用户1秒钟操作6次,遇到上述这个方法,只有乖乖地1秒后再来。别小看这1秒钟,一个数据库操作不过几毫秒。1秒延迟,足以降低系统负载,增加恶意用户成本。
附我用到的基于XMemcached实现:
- import net.rubyeye.xmemcached.MemcachedClient;
- import org.apache.log4j.Logger;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- /**
- *
- * @author Snowolf
- * @version 1.0
- * @since 1.0
- */
- @Component
- public class MemcachedManager {
- /**
- * 缓存时效 1天
- */
- public static final int CACHE_EXP_DAY = 3600 * 24;
- /**
- * 缓存时效 1周
- */
- public static final int CACHE_EXP_WEEK = 3600 * 24 * 7;
- /**
- * 缓存时效 1月
- */
- public static final int CACHE_EXP_MONTH = 3600 * 24 * 30 * 7;
- /**
- * 缓存时效 永久
- */
- public static final int CACHE_EXP_FOREVER = 0;
- /**
- * 冲突延时 1秒
- */
- public static final int MUTEX_EXP = 1;
- /**
- * 冲突键
- */
- public static final String MUTEX_KEY_PREFIX = "MUTEX_";
- /**
- * Logger for this class
- */
- private static final Logger logger = Logger
- .getLogger(MemcachedManager.class);
- /**
- * Memcached Client
- */
- @Autowired
- private MemcachedClient memcachedClient;
- /**
- * 缓存
- *
- * @param key
- * @param value
- * @param exp
- * 失效时间
- */
- public void cacheObject(String key, Object value, int exp) {
- try {
- memcachedClient.set(key, exp, value);
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- }
- logger.info("Cache Object: [" + key + "]");
- }
- /**
- * Shut down the Memcached Cilent.
- */
- public void finalize() {
- if (memcachedClient != null) {
- try {
- if (!memcachedClient.isShutdown()) {
- memcachedClient.shutdown();
- logger.debug("Shutdown MemcachedManager...");
- }
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- }
- }
- }
- /**
- * 清理对象
- *
- * @param key
- */
- public void flushObject(String key) {
- try {
- memcachedClient.deleteWithNoReply(key);
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- }
- logger.info("Flush Object: [" + key + "]");
- }
- /**
- * 冲突判定
- *
- * @param key
- */
- public boolean isMutex(String key) {
- return isMutex(key, MUTEX_EXP);
- }
- /**
- * 冲突判定
- *
- * @param key
- * @param exp
- * @return true 冲突
- */
- public boolean isMutex(String key, int exp) {
- boolean status = true;
- try {
- if (memcachedClient.add(MUTEX_KEY_PREFIX + key, exp, "true")) {
- status = false;
- }
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- }
- return status;
- }
- /**
- * 加载缓存对象
- *
- * @param key
- * @return
- */
- public <T> T loadObject(String key) {
- T object = null;
- try {
- object = memcachedClient.<T> get(key);
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- }
- logger.info("Load Object: [" + key + "]");
- return object;
- }
- }
PS:Redis的SETNX(即SET if Not eXists,类似于memcache的add)
相关链接:
Memcached笔记——(一)安装&常规错误&监控
Memcached笔记——(二)XMemcached&Spring集成
Memcached笔记——(三)Memcached使用总结
顶
踩

评论
好眼力![]()
各有利弊,需要根据业务需求权衡。![]()
写得非常好!应对高并发的时候,我们通常的思维是泄洪模式,通过一道又一道的防洪大堤将洪水分流,尤其是在应对数据要求不严厉的SNS这类产品,异步的保存数据值得提倡!
不过,更好的方式是:通过旁路式架构,解决代码层面的大部分压力。现在很多商城的商品展示和搜索都采用NOSQL技术来应对处理,异步增加或更新,并不显得那么重要了,更多的是通过产品和技术架构来调整,比如通过分析用户喜好,事先静态化搜索结果。
赞同,感谢分享!
最核心的优化,还是应当在产品层面多下工夫。找到用户-产品-技术,三方都能满足的平衡点。
各有利弊,需要根据业务需求权衡。![]()
写得非常好!应对高并发的时候,我们通常的思维是泄洪模式,通过一道又一道的防洪大堤将洪水分流,尤其是在应对数据要求不严厉的SNS这类产品,异步的保存数据值得提倡!
不过,更好的方式是:通过旁路式架构,解决代码层面的大部分压力。现在很多商城的商品展示和搜索都采用NOSQL技术来应对处理,异步增加或更新,并不显得那么重要了,更多的是通过产品和技术架构来调整,比如通过分析用户喜好,事先静态化搜索结果。
各有利弊,需要根据业务需求权衡。![]()
Memcached笔记——(四)应对高并发攻击【转】的更多相关文章
- Memcached笔记——(四)应对高并发攻击
近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最好成绩,1秒钟可以并发6次,赶在Database入库前,Cache进行Mis ...
- Memcached理解笔记4---应对高并发攻击
近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源.他们的最好成绩,1秒钟可以并发6次,赶在Database入库前,Cache进行Mis ...
- 《即时消息技术剖析与实战》学习笔记10——IM系统如何应对高并发
一.IM 系统的高并发场景 IM 系统中,高并发多见于直播互动场景.比如直播间,在直播过程中,观众会给主播打赏.送礼.发送弹幕等,尤其是明星直播间,几十万.上百万人的规模一点也不稀奇.近期随着武汉新型 ...
- SpringCloud应对高并发的思路
一.Eureka的高可用性 Eureka下面的服务实例默认每隔30秒会发送一个HTTP心跳给Eureka,来告诉Eureka服务还活着,每个服务实例每隔30秒也会通过HTTP请求向Eureka获取服务 ...
- 【Redis】1、Jedis对管道、事务以及Watch的操作来应对高并发
对于一个互联网平台来说,高并发是经常会遇到的场景.最有代表性的比如秒杀和抢购.高并发会出现三个特点: 1.高并发读取 2.高并发写入(一致性) 3.出现超卖问题 前端如何应对? 1.缓存静态数据,例如 ...
- java高并发编程(四)高并发的一些容器
摘抄自马士兵java并发视频课程: 一.需求背景: 有N张火车票,每张票都有一个编号,同时有10个窗口对外售票, 请写一个模拟程序. 分析下面的程序可能会产生哪些问题?重复销售?超量销售? /** * ...
- Nginx优化配置,轻松应对高并发
Nginx现在已经是最火的web服务器之一,尤其在静态分离和负载均衡方面,性能十分优越.接下来我们主要看下Nginx在高并发环境下的优化配置,主要是针对 nginx.conf 文件的属性设置.我们打开 ...
- 基于tomcat为了应对高并发模型实现webserver
在博客上,一个简单的AIOweb来样加工.查看AIO异步处理,依靠操作系统完成IO操作Proactor处理模型确实很强大,它可以实现高并发.高响应server一个很好的选择,但在tomcat中间con ...
- Linux下配置tomcat+apr+native应对高并发
摘要:在慢速网络上Tomcat线程数开到300以上的水平,不配APR,基本上300个线程狠快就会用满,以后的请求就只好等待.但是配上APR之后,Tomcat将以JNI的形式调用Apache HTTP服 ...
随机推荐
- .net source code
.NET 类库的强大让我们很轻松的解决常见问题,作为一个好专研的程序员,为了更上一层楼,研究CLR的基础类库实现是快速稳定的捷径. 一般场景下,采用 Reflector可以反射出.NET 的部分实现出 ...
- JS简单仿QQ聊天工具的制作
刚接触JS,对其充满了好奇,利用刚学到的一点知识,写了一个简单的仿QQ聊天的东西,其中还有很多的不足之处,有待慢慢提高. 功能:1.在输入框中输入内容,点击发送,即可在上方显示所输入内容. 2.点击‘ ...
- asp.net中Web使用Socket
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...
- Python 类 setattr、getattr、hasattr 的使用
#coding=utf-8 class Employee: '所有员工的基类' empCount = 0 def __init__(self, name, salary): self.name = n ...
- [BZOJ 2738] 矩阵乘法 【分块】
题目链接:BZOJ - 2738 题目分析 题目名称 “矩阵乘法” 与题目内容没有任何关系..就像VFK的 A+B Problem 一样.. 题目大意是给定一个矩阵,有许多询问,每次询问一个子矩阵中的 ...
- [OI笔记] 最长上升子序列与网络流建模
与最长上升子序列相关的网络流问题: 给定一个序列 A[1..n] ,求出 A 的最长上升子序列长度.并且回答下列询问: (1) 如果每个点只能用一次,能从 A 中取出几个最长上升子序列? (2) 如果 ...
- Kaggle Competition Past Solutions
Kaggle Competition Past Solutions We learn more from code, and from great code. Not necessarily alwa ...
- [mock]10月4日
第一次mock,CollabEdit开一个页面,开始做题.题目是,有方法pow(m,n),m和n都大于1,给出N,有顺序的打印出前N个pow(m,n)的结果.前一个是:4,8,9,16,... 然后在 ...
- c语言命名规则 [转载]
C语言变量名命名规则 一.程序风格: 1.严格采用阶梯层次组织程序代码: 各层次缩进的分格采用VC的缺省风格,即每层次缩进为4格,括号位于下一行. 要求相匹配的 ...
- C# 读取网络txt文件 并写在本地txt文件中
public void WriteStream() { try { stirng ImagesPath = ImagesPath + "\\2013-09-27.txt"; Htt ...