`
wxyfighting
  • 浏览: 191360 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

Memcached笔记——(四)应对高并发攻击

 
阅读更多

近半个月过得很痛苦,主要是产品上线后,引来无数机器用户恶意攻击,不停的刷新产品各个服务入口,制造垃圾数据,消耗资源。他们的最好成绩,1秒钟可以并发6次,赶在Database入库前,Cache进行Missing Loading前,强占这其中十几毫秒的时间,进行恶意攻击。


为了应对上述情况,做了如下调整:

  1. 更新数据时,先写Cache,然后写Database,如果可以,写操作交给队列后续完成。
  2. 限制统一帐号,同一动作,同一秒钟并发次数,超过1次不做做动作,返回操作失败。
  3. 限制统一用户,每日动作次数,超限返回操作失败。

要完成上述操作,同事给我支招。用Memcached的add方法,就可以很快速的解决问题。不需要很繁琐的开发,也不需要依赖数据库记录,完全内存操作。

以下实现一个判定冲突的方法:

Java代码收藏代码
  1. /**
  2. *冲突延时1秒
  3. */
  4. publicstaticfinalintMUTEX_EXP=1;
  5. /**
  6. *冲突键
  7. */
  8. publicstaticfinalStringMUTEX_KEY_PREFIX="MUTEX_";
  9. /**
  10. *冲突判定
  11. *
  12. *@paramkey
  13. */
  14. publicbooleanisMutex(Stringkey){
  15. returnisMutex(key,MUTEX_EXP);
  16. }
  17. /**
  18. *冲突判定
  19. *
  20. *@paramkey
  21. *@paramexp
  22. *@returntrue冲突
  23. */
  24. publicbooleanisMutex(Stringkey,intexp){
  25. booleanstatus=true;
  26. try{
  27. if(memcachedClient.add(MUTEX_KEY_PREFIX+key,exp,"true")){
  28. status=false;
  29. }
  30. }catch(Exceptione){
  31. logger.error(e.getMessage(),e);
  32. }
  33. returnstatus;
  34. }

做个说明:

选项 说明
add 仅当存储空间中不存在键相同的数据时才保存
replace 仅当存储空间中存在键相同的数据时才保存
set 与add和replace不同,无论何时都保存

也就是说,如果add操作返回为true,则认为当前不冲突!

回归场景,恶意用户1秒钟操作6次,遇到上述这个方法,只有乖乖地1秒后再来。别小看这1秒钟,一个数据库操作不过几毫秒。1秒延迟,足以降低系统负载,增加恶意用户成本。

附我用到的基于XMemcached实现:

Java代码收藏代码
  1. importnet.rubyeye.xmemcached.MemcachedClient;
  2. importorg.apache.log4j.Logger;
  3. importorg.springframework.beans.factory.annotation.Autowired;
  4. importorg.springframework.stereotype.Component;
  5. /**
  6. *
  7. *@authorSnowolf
  8. *@version1.0
  9. *@since1.0
  10. */
  11. @Component
  12. publicclassMemcachedManager{
  13. /**
  14. *缓存时效1天
  15. */
  16. publicstaticfinalintCACHE_EXP_DAY=3600*24;
  17. /**
  18. *缓存时效1周
  19. */
  20. publicstaticfinalintCACHE_EXP_WEEK=3600*24*7;
  21. /**
  22. *缓存时效1月
  23. */
  24. publicstaticfinalintCACHE_EXP_MONTH=3600*24*30;
  25. /**
  26. *缓存时效永久
  27. */
  28. publicstaticfinalintCACHE_EXP_FOREVER=0;
  29. /**
  30. *冲突延时1秒
  31. */
  32. publicstaticfinalintMUTEX_EXP=1;
  33. /**
  34. *冲突键
  35. */
  36. publicstaticfinalStringMUTEX_KEY_PREFIX="MUTEX_";
  37. /**
  38. *Loggerforthisclass
  39. */
  40. privatestaticfinalLoggerlogger=Logger
  41. .getLogger(MemcachedManager.class);
  42. /**
  43. *MemcachedClient
  44. */
  45. @Autowired
  46. privateMemcachedClientmemcachedClient;
  47. /**
  48. *缓存
  49. *
  50. *@paramkey
  51. *@paramvalue
  52. *@paramexp
  53. *失效时间
  54. */
  55. publicvoidcacheObject(Stringkey,Objectvalue,intexp){
  56. try{
  57. memcachedClient.set(key,exp,value);
  58. }catch(Exceptione){
  59. logger.error(e.getMessage(),e);
  60. }
  61. logger.info("CacheObject:["+key+"]");
  62. }
  63. /**
  64. *ShutdowntheMemcachedCilent.
  65. */
  66. publicvoidfinalize(){
  67. if(memcachedClient!=null){
  68. try{
  69. if(!memcachedClient.isShutdown()){
  70. memcachedClient.shutdown();
  71. logger.debug("ShutdownMemcachedManager...");
  72. }
  73. }catch(Exceptione){
  74. logger.error(e.getMessage(),e);
  75. }
  76. }
  77. }
  78. /**
  79. *清理对象
  80. *
  81. *@paramkey
  82. */
  83. publicvoidflushObject(Stringkey){
  84. try{
  85. memcachedClient.deleteWithNoReply(key);
  86. }catch(Exceptione){
  87. logger.error(e.getMessage(),e);
  88. }
  89. logger.info("FlushObject:["+key+"]");
  90. }
  91. /**
  92. *冲突判定
  93. *
  94. *@paramkey
  95. */
  96. publicbooleanisMutex(Stringkey){
  97. returnisMutex(key,MUTEX_EXP);
  98. }
  99. /**
  100. *冲突判定
  101. *
  102. *@paramkey
  103. *@paramexp
  104. *@returntrue冲突
  105. */
  106. publicbooleanisMutex(Stringkey,intexp){
  107. booleanstatus=true;
  108. try{
  109. if(memcachedClient.add(MUTEX_KEY_PREFIX+key,exp,"true")){
  110. status=false;
  111. }
  112. }catch(Exceptione){
  113. logger.error(e.getMessage(),e);
  114. }
  115. returnstatus;
  116. }
  117. /**
  118. *加载缓存对象
  119. *
  120. *@paramkey
  121. *@return
  122. */
  123. public<T>TloadObject(Stringkey){
  124. Tobject=null;
  125. try{
  126. object=memcachedClient.<T>get(key);
  127. }catch(Exceptione){
  128. logger.error(e.getMessage(),e);
  129. }
  130. logger.info("LoadObject:["+key+"]");
  131. returnobject;
  132. }
  133. }


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics