最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis教程之代理ip池設(shè)計方法詳解

 更新時間:2017年01月20日 10:21:00   投稿:daisy  
這篇文章主要介紹了Redis實現(xiàn)代理ip池的設(shè)計方法,文中給出了詳細(xì)的介紹與示例代碼,相信對大家的理解和學(xué)習(xí)具有一定的參考借鑒價值,有需要的朋友們下面來一起看看吧。

前言

眾所周知代理 ip 因為配置簡單而且廉價,經(jīng)常用來作為反反爬蟲的手段,但是穩(wěn)定性一直是其詬病。篩選出優(yōu)質(zhì)的代理 ip 并不簡單,即使付費購買的代理 ip 源,賣家也不敢保證 100% 可用;另外代理 ip 的生命周期也無法預(yù)知,可能上一秒能用,下一秒就撲街了?;谶@些原因,會給使用代理 ip 的爬蟲程序帶來很多不穩(wěn)定的因素。要排除代理 ip 的影響,通常的做法是建一個代理 ip 池,每次請求前來池子取一個 ip,用完之后歸還,保證池子里的 ip 都是可用的。本文接下來就探討一下,如何使用 Redis 構(gòu)建代理 ip 池,實現(xiàn)自動更新,自動擇優(yōu)。

整體流程

由上圖所示,左側(cè)是形成了整個流程的閉環(huán),從爬蟲程序以獨占的方式拿到一個代理 ip 到爬取完成歸還 ip。這個流程其實是不太嚴(yán)謹(jǐn)?shù)模绻老x程序異常中斷,就會導(dǎo)致 ip 無法歸還,就會導(dǎo)致這個 ip 無法循環(huán)利用。但是由于代理 ip 本身的特點,量多而且循環(huán)利用的價值并不大,所以這種情況就let it go。

上面也提到 ip 是以獨占的方式獲取,如果是去爬兩個毫不相關(guān)的網(wǎng)站,本來一個 ip 就可以,可現(xiàn)在需要兩個。為了資源最大化使用,這里引入了頻道 ip 池和總代理 ip 池。兩個網(wǎng)站就當(dāng)做兩個頻道,各自獨占,互不相關(guān);總池子就是保存所有的 ip,每個頻道都共享。假設(shè)只有一個 ip:1.1.1.1 在總池子,爬 A 網(wǎng)站會把它從總池子取到 A 頻道的 ip 池,然后 A 爬蟲程序從 A 頻道 ip 池取出 1.1.1.1 進(jìn)行使用,這時 1.1.1.1 依然在總池子里,但 A 頻道的 ip 池已經(jīng)不包含 1.1.1.1 了;爬 B 網(wǎng)站也是一樣的流程拿到 1.1.1.1,只是從 B 自己的頻道池獲取。下面就詳細(xì)說說總池子和頻道池子。

總代理 ip 池

總池子的作用就是共享所有可用的 ip,但是僅作為存儲 ip 的池子并不能實現(xiàn)自動擇優(yōu)啊,這里的擇優(yōu)通常是希望延遲低速度快的 ip 更容易被篩選出,所以我們希望池子中的 ip 是根據(jù)它們的延時升序排列,借助 Redis 的 Sorted Sets 數(shù)據(jù)結(jié)構(gòu)即可實現(xiàn),用延時表示 score,ip 表示 member。

使用 ZADD 添加新 ip 或更新 ip 的延遲:

> ZADD proxy_global_ips 200 1.1.1.1:8080 100 2.2.2.2:80 300 3.3.3.3:8888
(integer) 3

使用 ZRANGE 獲取 ip,可以指定獲取的個數(shù),比如取兩個:

> ZRANGE proxy_global_ips 0 1 WITHSCORES
1) "2.2.2.2:80" 
2) "100" 
3) "1.1.1.1:8080" 
4) "200" 

頻道 ip 池

頻道 ip 池的作用是為了最大化使用總池子中的 ip,并且隔離其他頻道的 ip 池。由于一個 ip 使用次數(shù)過多是有很大的概率被目標(biāo)網(wǎng)站屏蔽掉,所以這里也需要進(jìn)行擇優(yōu),應(yīng)該優(yōu)先篩選出使用次數(shù)少的 ip,同理也是使用 Sorted Sets,使用次數(shù)表示 score,ip 表示 member,這里與總池子明顯的不同之處是 key 不是固定的,需要把頻道名稱組合進(jìn)去,這樣保證頻道之間的隔離,如頻道 abc 的 key:proxy_channel_abc_ips。

由于頻道池子中的 ip 是要以獨占的方式取出,我們需要一個 ZPOP 的方法,奈何 Redis 本身沒有,還好可以通過 Lua 模擬,在一個原子操作下取出 ip,然后刪除:

> eval "local el = redis.call('zrange', KEYS[1], 0, 0, 'WITHSCORES'); redis.call('zrem', KEYS[1], el[1]); return el;" 1 proxy_channel_abc_ips

往頻道 ip 池添加 ip:

> ZADD proxy_channel_abc_ips INCR 0 1.1.1.1:8080

這里與總池子不同的是多了一個 INCR 選項,這是 Redis 3.0.2 版本后才支持的新特性,即指定在 ZADD 時發(fā)生 member 沖突采取的處理方式,INCR 顧名思義是沖突后累加 score 的方式,為什么要用這個選項,看看下面這個流程:

  1. 在頻道池子中只有 1.1.1.1,使用次數(shù)為 10;總池子也有 1.1.1.1,而且排在第一個
  2. 線程 A 取出 1.1.1.1
  3. 線程 B 從頻道池子取 ip,沒取到,從總池子補(bǔ)充 ip 到頻道池子:ZADD proxy_channel_abc_ips 0 1.1.1.1;取出 1.1.1.1
  4. 線程 A 歸還 1.1.1.1:ZADD proxy_channel_abc_ips 11 1.1.1.1
  5. 線程 B 歸還 1.1.1.1:ZADD proxy_channel_abc_ips 1 1.1.1.1

第 5 步結(jié)束后,ip 1.1.1.1 的計數(shù)被錯誤地重置為 1,而不是我們預(yù)期的 12。使用 INCR 選項就可以避免這個尷尬,其實這也只能保證最終計數(shù)正確,中途還是會有些非預(yù)期的情況,如:

  1. 在頻道池子中有 1.1.1.1,使用次數(shù)為 10,還有 2.2.2.2,使用次數(shù)為 2;總池子也有 1.1.1.1,而且排在第一個
  2. 線程 A 取出 1.1.1.1
  3. 線程 B 取出 2.2.2.2
  4. 線程 C 從頻道池子取 ip,沒取到,從總池子補(bǔ)充 ip 到頻道池子:ZADD proxy_channel_abc_ips 0 1.1.1.1;取出 1.1.1.1
  5. 線程 C 歸還 1.1.1.1:ZADD proxy_channel_abc_ips INCR 1 1.1.1.1
  6. 線程 B 歸還 2.2.2.2:ZADD proxy_channel_abc_ips INCR 3 2.2.2.2
  7. 線程 D 來池子取 ip,按使用次數(shù)少的被分配了 1.1.1.1,這就不是我們期望的,1.1.1.1 實際已經(jīng)用了 12 次,我們更希望 2.2.2.2 被取出

如果要避免這個問題,一個簡單粗暴的辦法就是增加頻道池子的容量,讓 ip 數(shù)永遠(yuǎn)大于并發(fā)的線程數(shù)。

更新

與 ip 有關(guān)的兩個屬性:延時(爬取頁面所花的時間)和使用次數(shù)。上面只講到了根據(jù)它們自動擇優(yōu),這里的就來說下它們是如何更新的。延時和使用次數(shù)的更新需要爬蟲程序的配合,程序中要記錄時間和遞增使用次數(shù),在歸還 ip 時要將最新值帶回給總池子和頻道池子。上面頻道 ip 池的例子也有提及,每次歸還 ip 都要將最新的使用次數(shù)帶上,其次還要將 ip 的延時更新到總池子里面。如果歸還 ip 時出現(xiàn)使用失敗的情況,就要將該 ip 從總池子里刪除掉,保證該 ip 不會再被使用,至于當(dāng)前的頻道池不用歸還就行了。其他頻道池不作任何處理,因為 ip 在當(dāng)前頻道不可用,一般都是因為被屏蔽,其他頻道依然可以使用,即使確實都不能使用,也會在其他頻道歸還 ip 時被刪除。

這兩個屬性其實也可以都在 Redis 中更新,在獲取 ip 時,使用 Hashs 保存 ip 對應(yīng)的獲取時間和使用次數(shù);在歸還時從 Hashs 中取出時間計算出延時,取出使用次數(shù)并加 1,再分別更新到總池子和頻道池子中。而且這還能避免上面提到的獲取 ip 不符合預(yù)期的問題。

總結(jié)

放在 Redis 中更新的方法也有弊端,延時會包含獲取和歸還的傳輸時間,如果爬蟲程序獲取一個 ip 多次使用,會造成使用次數(shù)統(tǒng)計偏少。當(dāng)然也可以通過在程序中多次調(diào)用 Redis 更新 ip 的屬性來解決,這樣增加了整個流程的復(fù)雜性,需要自己權(quán)衡。

個人還是傾向在程序中記錄,最后更新到 Redis 中。這個方案邏輯確實不夠嚴(yán)謹(jǐn),但是出現(xiàn)問題也不會導(dǎo)致嚴(yán)重后果。程序的健壯性也不是不允許出現(xiàn) bug,而是出現(xiàn) bug 有很好的容錯性。

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。

相關(guān)文章

  • Redis筆記點贊排行榜的實現(xiàn)示例

    Redis筆記點贊排行榜的實現(xiàn)示例

    探店筆記類似點評網(wǎng)站的評價,本文主要介紹了Redis筆記點贊排行榜的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-01-01
  • Redis基本數(shù)據(jù)類型哈希Hash常用操作命令

    Redis基本數(shù)據(jù)類型哈希Hash常用操作命令

    這篇文章主要為大家介紹了Redis基本數(shù)據(jù)類型哈希Hash常用操作,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • Redis Value過大問題(鍵值過大)

    Redis Value過大問題(鍵值過大)

    這篇文章主要介紹了Redis Value過大問題(鍵值過大),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Redis分布式鎖python-redis-lock使用方法

    Redis分布式鎖python-redis-lock使用方法

    這篇文章主要介紹了Redis分布式鎖python-redis-lock使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • 詳解Centos7下配置Redis并開機(jī)自啟動

    詳解Centos7下配置Redis并開機(jī)自啟動

    本篇文章主要介紹了Centos7下配置Redis并開機(jī)自啟動,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2016-11-11
  • Redis概述及l(fā)inux安裝redis的詳細(xì)教程

    Redis概述及l(fā)inux安裝redis的詳細(xì)教程

    這篇文章主要介紹了Redis概述及l(fā)inux安裝redis的詳細(xì)教程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-10-10
  • 詳解Redis緩存預(yù)熱的實現(xiàn)方法

    詳解Redis緩存預(yù)熱的實現(xiàn)方法

    緩存預(yù)熱是一種在程序啟動或緩存失效之后,主動將熱點數(shù)據(jù)加載到緩存中的策略,本文將給大家分享一下如何實現(xiàn)Redis的緩存預(yù)熱,文中有詳細(xì)的實現(xiàn)代碼,需要的朋友可以參考下
    2023-10-10
  • redis使用zset實現(xiàn)延時隊列的示例代碼

    redis使用zset實現(xiàn)延時隊列的示例代碼

    本文主要介紹了redis使用zset實現(xiàn)延時隊列的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Redis配置外網(wǎng)可訪問(redis遠(yuǎn)程連接不上)的方法

    Redis配置外網(wǎng)可訪問(redis遠(yuǎn)程連接不上)的方法

    默認(rèn)情況下,當(dāng)我們在部署了redis服務(wù)之后,redis本身默認(rèn)只允許本地訪問。Redis服務(wù)端只允許它所在服務(wù)器上的客戶端訪問,如果Redis服務(wù)端和Redis客戶端不在同一個機(jī)器上,就要進(jìn)行配置。
    2022-12-12
  • RedisTemplate訪問Redis的更好方法

    RedisTemplate訪問Redis的更好方法

    這篇文章主要為大家介紹了RedisTemplate訪問Redis的更好方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01

最新評論

德兴市| 绥中县| 玉树县| 黄浦区| 玉溪市| 伽师县| 兴国县| 仁布县| 紫云| 阳西县| 军事| 襄樊市| 安宁市| 从江县| 新河县| 昂仁县| 汉寿县| 苍溪县| 信丰县| 页游| 龙里县| 都匀市| 沂南县| 平南县| 全州县| 佛山市| 丹江口市| 青河县| 时尚| 兴文县| 松江区| 乐至县| 永嘉县| 闸北区| 修武县| 临颍县| 楚雄市| 鹤峰县| 青浦区| 许昌市| 蓬溪县|