爬蟲-反爬與反反爬(12)
為什麼用redis
解決伺服器CPU記憶體壓力
方案一、存在Cookie中
此種方案需要將Session資料以Cookie的形式存在客戶端,不安全,網路負擔效率低
方案二、存在檔案伺服器或者是資料庫裡
此種方案會導致大量的IO操作,效率低.
方案三、Session複製
此種方案會導致每個伺服器之間必須將Session廣播到叢集內的每個節點,Session資料會冗餘,節點越多浪費越大,存在廣播風暴問題.
方案四、存在Redis中
-
目前來看,此種方案是最好的。將Session資料存在記憶體中,每臺伺服器都從記憶體中讀取資料,速度快,結構還相對簡單
-
將活躍的資料快取到Redis中,客戶端的請求先打到快取中來獲取對應的資料,如果能獲取到,直接返回,不需要從MySQL中讀取。如果快取中沒有,再從MySQL資料庫中讀取資料,將讀取的資料返回並存一份到Redis中,方便下次讀取
-
適用於對資料高併發的讀寫、海量資料的讀寫、對資料高可擴充套件性的
redis簡介及安裝
簡介
Redis是一個開源的key-value儲存系統。和Memcached類似,它支援儲存的value型別相對更多,包括string(字串)、list(連結串列)、set(集合)、zset(sorted set --有序集合)和hash(雜湊型別)。這些資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,Redis支援各種不同方式的排序。
安裝
https://www.cnblogs.com/marvinn/p/11081106.html
redis的五大資料型別
基本操作
1\
key
-
String是Redis最基本的型別,你可以理解成與Memcached一模一樣的型別,一個key對應一個value
-
String型別是二進位制安全的。意味著Redis的string可以包含任何資料。比如jpg圖片或者序列化的物件 。
-
String型別是Redis最基本的資料型別,一個Redis中字串value最多可以是512M
常用操作
2\
list
-
單鍵多值
-
Redis 列表是簡單的字串列表,按照插入順序排序。你可以新增一個元素導列表的頭部(左邊)或者尾部(右邊)。
-
它的底層實際是個雙向連結串列,對兩端的操作效能很高,通過索引下標的操作中間的節點效能會較差
3
4\
Set
- Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動排重的,當你需要儲存一個列表資料,又不希望出現重複資料時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要介面,這個也是list所不能提供的
- Redis的Set是string型別的無序集合。它底層其實是一個value為null的hash表,所以新增,刪除,查詢的複雜度都是O(1)
5\
Hash
現有一個JavaBean物件,在Redis中如何存?
6
7\
Zset
-
Redis有序集合zset與普通集合set非常相似,是一個沒有重複元素的字串集合。不同之處是有序集合的每個成員都關聯了一個評分(score) ,這個評分(score)被用來按照從最低分到最高分的方式排序集合中的成員。集合的成員是唯一的,但是評分可以是重複了
-
因為元素是有序的, 所以你也可以很快的根據評分(score)或者次序(position)來獲取一個範圍的元素。訪問有序集合的中間元素也是非常快的,因此你能夠使用有序集合作為一個沒有重複成員的智慧列表。
\8
redis的相關配置
https://blog.csdn.net/P_ning/article/details/106241421
redis的Java客戶端
-
匯入jar包
Commons-pool-1.6.jar
Jedis-2.1.0.jar -
注意事項
-
禁用Linux的防火牆:Linux(CentOS7)裡執行命令 : systemctl stop firewalld.service
-
redis.conf中註釋掉bind 127.0.0.1 ,然後 protect-mode no
- 測試是否聯通
\9
package com.atguigu.test;
import redis.clients.jedis.Jedis;
public class Test {
public static void main(String[] args) {
Jedis jedis = new Jedis("192.168.16.128",6379);
String result = jedis.ping();
System.out.println(result);
jedis.set("a", "a");
String a = jedis.get("a");
System.out.println(a);
jedis.close();
}
}
- 完成一個手機驗證碼功能
-
匯入jar包
\10 -
index.jsp
1、index.jsp中
插入一些檔案
<script src="/Verify_code/static/jquery/jquery-3.1.0.js"
></script>
<link href="/Verify_code/static/bs/css/bootstrap.min.css"
rel="stylesheet" />
<script src="/Verify_code/static/bs/js/bootstrap.min.js"
></script>
主體中
<div class="container">//1、boostrap中的樣式,可以用來控制是否在12個格子中
<div class="row">//2、與container配合減少一些空白
<div id="alertdiv" class="col-md-12">//一行12個
<form class="navbar-form navbar-left"><u>role</u>="search" id="codeform">
<div class="form-group">
<input type="text" class="form-control" <u>placeholder</u>="填寫手機號" name="phone_no">//加入form-control會使用boostrap自帶的input框
<button type="button" class="btn btn-default" id="sendCode">傳送驗證碼</button>//name可重複、value不可重複
<br><font id="countdown" color="red" ></font> <br>
<input type="text" class="form-control" <u>placeholder</u>="填寫驗證碼" name="verify_code">
<button type="button" class="btn btn-default" id="verifyCode">確定</button>
<font id="result" color="green" ></font><font id="error" color="red" ></font>
</div>
</form>
</div>
</div>
</div>
1、https://blog.csdn.net/weixin_42097173/article/details/80381896</u>
2、https://www.cnblogs.com/olivertian/p/11119784.html</u>
3、https://blog.csdn.net/wem603947175/article/details/83004364</u>
javascript中
var t=120;//設定倒計時的時間
var interval;
function refer(){
$("#countdown").text("請於"+t+"秒內填寫驗證碼 "); // 顯示倒計時
t--; // 計數器遞減
if(t<=0){
clearInterval(interval);
$("#countdown").text("驗證碼已失效,請重新發送! ");
}
}
$(function(){//整個頁面載入完成後
$("#sendCode").click( function () {//繫結傳送驗證碼按鈕
$.post("/Verify_code/CodeSenderServlet",$("#codeform").serialize(),function(data){//1、-跳轉訪問路徑、-form表單中資訊序列化資訊、反應(傳回來的資訊)
if(data=="true"){//2、定時器倒計時
t=120;
clearInterval(interval);
interval= setInterval("refer()",1000);//啟動1秒定時
}else if (data=="limit"){
clearInterval(interval);
$("#countdown").text("單日傳送超過次數! ")
}
});
});
$("#verifyCode").click( function () {//繫結驗證確定按鈕
$.post("/Verify_code/CodeVerifyServlet",$("#codeform").serialize(),function(data){
if(data=="true"){
$("#result").attr("color","green");//3、設定或返回備選元素的屬性或值
$("#result").text("驗證成功");
clearInterval(interval);
$("#countdown").text("");
}else{
$("#result").attr("color","red");
$("#result").text("驗證失敗");
}
});
});
});
1、<u>https://www.cnblogs.com/webapi/p/10550185.html</u>
2、<u>https://blog.csdn.net/YDesire/article/details/81124331</u>
3、<u>https://www.cnblogs.com/blmlove/p/12701722.html</u>
2、CodeSenderServlet
@WebServlet("/CodeSenderServlet")
public class CodeSenderServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public CodeSenderServlet() {
super();
// TODO Auto-generated constructor stub
}
private String getCode(int length) {
String code = "";
Random random = new Random();
for(int i = 0; i < length; i++) {
int rand = random.nextInt(10);//1、生成隨機數字
code += rand;
}
return code;
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取手機號
String phone_no = request.getParameter("phone_no");
//獲取驗證碼
String code = getCode(6);
//拼接key
String codeKey = "Verify_code:" + phone_no + ":code";//Verify_code:12345:code
String countKey = "Verify_code:" + phone_no + ":count";
Jedis jedis = new Jedis("192.168.16.128", 6379);
//判斷髮送驗證碼的次數
String count = jedis.get(countKey);
if(count == null) {
//代表第一次
jedis.setex(countKey, 24*60*60, "1");
}else if(Integer.parseInt(count) <= 2) {
jedis.incr(countKey);
}else if(Integer.parseInt(count) > 2) {
response.getWriter().print("limit");
jedis.close();
return ;
}
//向<u>redis</u>中進行儲存,以手機號為鍵,以驗證碼為值
jedis.setex(codeKey, 120, code);
jedis.close();
response.getWriter().print(true);
}
}
1、https://www.cnblogs.com/hm1990hpu/p/8875928.html</u>
3、CodeVerifyServlet
@WebServlet("/CodeVerifyServlet")
public class CodeVerifyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public CodeVerifyServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//獲取驗證碼和手機號
String phone_no = request.getParameter("phone_no");
String verify_code = request.getParameter("verify_code");
//拼接key
String codeKey = "Verify_code:" + phone_no + ":code";
//從<u>redis</u>中獲取手機號所對應的驗證碼
Jedis jedis = new Jedis("192.168.16.128", 6379);
String code = jedis.get(codeKey);
if(code.equals(verify_code)) {
response.getWriter().print(true);
}
jedis.close();
}
}