16 通過 memcached 實現領號排隊功能及 python 隊列實例

前言:

前段時間寫的那個域用戶平台,要做大量的新功能運維測試,據說要抄 IT 組,讓那幫人到搞,跑一下! 尼瑪,這可嚇壞了我了。 因為平台要和 windows 做大量的交互,那邊 powershell 又很不給力,改成多線程版本後,出現莫名的問題,很讓人鬧心。現在的狀態是,client 給 server 端可以同時推送兩片信息,要是多的話,powershell 實在處理不了,我只能放到 queue 隊列裡面了。

現在很多的堵塞都是在 windows 那邊,我這邊因為用的是 tornado,對於用戶訪問是無壓力的,但是 windows 那邊不能同時運行多了,不然會提示 bug。。。

ad 的信息我暫時還沒有批量的同步過來,所以只能單點搞了 ~

一直在想咋才能不出醜。所以做了好多的限制,比如短信接口的 token 機制,用戶更新接口的次數的限制。 現在唯一的節點就是和 win 那邊的交互。別等到了週一的時候,一幫人把 獲取手機號碼、修改密碼、更新用戶信息的接口給點爆了。

突然想到 12306 那個渣渣,可以用排隊呀。。。 這樣的話,最少能看起來很高端的樣子。

圖片 16.1 pic

我的前端實現 ~

用戶點擊的時候,我會從後端的 api 查看隊列中的數目,以及有誰排在我的前面 ~

$("#dialog").hide;$("#mailname").focus;$("#service").click(function{    $.ajax({     type: "POST",     url: "/queue",     data : $("#form_service").serialize,     dataType: "html",      timeout:5000,     error: function{  alert(\'nima,超時了\');     },     success: function(data,status){if( data=="ok"){  <!--  alert (data+status+"成功了");-->    var a=$("input[name=mailname]").val;    window.location.href="/mailpost?mailname="+a; }else{     $(\'#myModal\').modal;    }}    });});});  

後端的實現~

不用 redis 做隊列的原因是,python 調用隊列的時候總是莫名的關閉,卸載安裝了好多遍。。。怪事 ~ 和 powershell 多線程一樣都很怪~

安裝配置 memcached 環境,簡單點直接 yum ~

需要編譯安裝的朋友,用下面的腳本~

wget https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gztar xzf libevent-2.0.21-stable.tar.gzcd libevent-2.0.21-stable./configuremakemake installwget http://memcached.googlecode.com/files/memcached-1.4.15.tar.gztar vxzf memcached-1.4.15.tar.gzcd memcached-1.4.15./configure --prefix=/usr/local/webserver/memcachedmakemake install  

圖片 16.2 pic

啟動 memcached 命令是: /usr/local/memcached/bin/memcached -d -m 100 -c 1000 -u root -p 11211

-d 選項是啟動一個守護進程-m 是分配給 Memcache 使用的內存數量,單位是 MB,默認 64 MB-M return error on memory exhausted (rather than removing items)-u 是運行 Memcache 的用戶,如果當前為 root 的話,需要使用此參數指定用戶-l 是監聽的服務器 IP 地址,默認為所有網卡-p 是設置 Memcache 的 TCP 監聽的端口,最好是 1024 以上的端口-c 選項是最大運行的並發連接數,默認是 1024-P 是設置保存 Memcache 的 pid 文件-f chunk size growth factor (default: 1.25)-I Override the size of each slab page. Adjusts max item size(1.4.2 版本新增)  

有朋友可能沒有接觸過 memcached,也有沒有用 python 操作 memcached 的。 我在這裡就簡單操作下,讓大家瞅瞅哈~

python 操作 memcached 需要安裝 python-memcached 模塊

pip install python-memcached

import memcache mc=memcache.Client([\'127.0.0.1:11211\'],debug=0) mc.set(「xiaorui.cc」,」fengyun」) value=mc.get(「xiaorui.cc」) mc.set(「another_key」,3) mc.delete(「another_key) mc.set(「key」,」1〞) #用於自動增量/減量的必須是字符串 mc.incr(「key」) mc.decr(「key」) 標準的使用 memcache 作為數據庫緩存的方法如下: key=derive_key(obj) obj=mc.get(key) if not obj: obj=backend_api.get(…) mc.set(obj) #現在可以操作 obj  

構造函數
delete(key,time=0)
刪除某個鍵。time 的單位是秒,確保特定時間內的 set/update 操作會失敗。返回 1 成功,0 失敗。
incr(key,delta=1)
給自增量變量加上 delta,默認為 1。
decr(key,delta=1)
給自減量變量減去 delta,默認為 1。
add(key,val,time=0,min_compress_len=0)
添加一個鍵值對,內部調用 _set 方法。
replace(key,val,time=0,min_compress_len=0)
替換值,內部調用_set 方法。
set(key,val,time=0,min_compress_len=0)
無條件的設置鍵值對。time 設置超時,單位是秒。min_compress_len 用於設置 zlib 壓縮。內部調用_set 方法。
set_multi(mapping,time=0,key_prefix=」,min_compress_len=0)
設置多個鍵值對。
get(key)
獲取值。出錯則返回 None。
get_multi(keys,key_prefix=」)
獲取多個鍵的值,返回字典。keys 為健明列表。key_prefix 是鍵名前綴,可以最終構成 key_prefix+key 的完整鍵名。與 set_multi 中一樣。

Memcached 本身沒有的實現的,但是高手還是多呀,有個高手開源了一個 memcached 隊列的 python 實現方案。

RedQueue 參考了 github 開源項目 starling(ruby 寫的), twitter 曾經使用伊做隊列服務,後來改成了用 scala 寫的 scaling(kestrol) . Redqueue 用 python 的高性能框架 tornado 寫成。支持 memcache 協議, 也就是說偽裝成一個 memcache server,由於許多語言都有了 memcache 庫,也就有了應用 redqueue 的土壤。

redqueue 是可以持久化的,使用日誌文件記錄所有的操作,當系統重啟的時候,可以恢復沒有處理的未超時任務重新處理。 這樣對於 server 端的容錯性有好處。更進一步的是,redqueue 具有客戶端容錯性,客戶通過 get 命令從隊列中得到一個任務,使用 delete 刪除這個任務,如果沒有 delete 而因某種原因退出了,則該任務會被 server 重新塞入隊列等待處理。

圖片 16.3 pic

關於 redqueue 的 python 應用小 demo ~

 # 引入 memcache 模塊import memcache #初始化客戶端mc = memcache.Client([\'127.0.0.1:12345\'])  # 假設 redqueue server 守候在 localhost 的 12345 端口 # 發佈一個項目到 key myqueue 中, 值為"Hello world"mc.set("xiaorui", "good") # 消費者從 queue server 中取出一個任務, 並打印print mc.get("xiaorui")  # 應該是 good # 刪除一個任務,必須做,否則 server 會認為客戶端異常發生了,而重新隊列處理該任務 # 什麼時候客戶端確認該任務已經確保執行了,就可以 delete 掉。在這之間,任務不會被其他客戶端執行。mc.delete("xiaorui")  

圖片 16.4 pic

這個是作者給的過程:

== Install and Run Install tornado and (optional) python-memcached for client testing Get the source from [email protected]:superisaac/redqueue.git Install % python setup.py install Make the log dir % mkdir -p log Run the server % redqueue_server.py For more options please run % redqueue_server.py --help== Reserve/delete mode   Reserve/delete mode is currently the sole mode, once an item is fetched, a delete request must be send later to mark the item is used, or else the item will be recycled back later.   >>> mc.set(\'abc\', \'123\')   >>> v = mc.get(\'abc\')   >>> if v is not None:   >>>     mc.delete(\'abc\')  

現在隊列有了,我給大家說下,我那邊是咋實現排隊的~

當用戶訪問頁面下一步的時候,我會判斷隊列,要是他前面有人在進行,我會給他重定向到最初的頁面。當別人搞完了,他才可以的。

但是這樣的話,還有個問題,那就是要是有 5 個人同時進了隊列裡面了,我給他們已經排序了,要是老大和老二,他不在進行了,老三的話,咋辦。。。 這時候就需要配置隊列裡面的值和 kv 的一個值做時間的生效。 也就是說 老大和老二要是在指定的時間內沒有完成的話,我會把他們踢出去,這樣老三就成老大了。

本文出自 「峰雲,就她了。」 博客,謝絕轉載!

《Python實戰-從菜鳥到大牛的進階之路》