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服 ...
随机推荐
- CALayer -- 备忘
CALayer layer是层,每个view上都会最少有一个layer,view上的可视化内容其实都是层. CALayer展示实例 let customView = UIView(frame: CGR ...
- hdu 4433
一道dp题,虽然知道是dp,但是不会做: 学习了ACM_cxlove大神的代码,终于明白了: 搬运工: dp[i][j][k]表示 前i个已经完全匹配,而这时候,第i+1个已经加了j位,第i+2位已经 ...
- ANDROID_MARS学习笔记_S04_001_OAuth简介
一.OAuth简介
- QQ协议的TEA加解密算法
QQ通讯协议里的加解密算法. #include <stdio.h> #include <stdlib.h> #include <memory.h> #include ...
- 如何在C++中使用WebService
gsoap主页 http://sourceforge.net/projects/gsoap2 使用gsoap生成所需的WebService 下载后的gsoap包为:(点击到我的资源中下载) 将他解 ...
- leetcode面试准备: Substring with Concatenation of All Words
leetcode面试准备: Substring with Concatenation of All Words 1 题目 You are given a string, s, and a list o ...
- JavaScript 判断对象是否为空
/** **判断是否null *@param data */ function isNull(data) { return (data == "" || data == u ...
- Android ActivityManagerService 基本构架详解
学习AmS有段时日了,总结下,也好梳理一下自己的思路.小兵一个,有些地方理解不对,大家可以互相讨论,交流才有进步吗~~~ AmS可以说是Android上层系统最核心的模块之一,其主要完成管理应用进程的 ...
- MySQL源码 优化器
完成了sql的解析过程后,开始进入优化器: 调用的流程分为: mysql_select: JOIN::prepare: JOIN::optimize: ...
- bzoj1079
50%的数据很好考虑,基本的dp了 关键到了100%,如果用每种颜色有ci种这种常规的写法,显然5^15会爆空间 考虑到反过来,ci<=5, 15^5是不会爆空间的 又想到,每一种颜色,如果数量 ...