測(cè)試平臺(tái)系列(80) 封裝Redis客戶端

大家好~我是米洛辞色!

我正在從0到1打造一個(gè)開源的接口測(cè)試平臺(tái), 也在編寫一套與之對(duì)應(yīng)的完整教程疯暑,希望大家多多支持砚哗。

歡迎關(guān)注我的龔仲耗測(cè)試開發(fā)坑貨怔揩,獲取最新文章教程!

回顧

上一節(jié)我們編寫了Redis的相關(guān)配置編輯頁面右蕊,博主這里也趁熱打鐵琼稻,把前端頁面完善了。(可能會(huì)有一點(diǎn)點(diǎn)小問題饶囚,但應(yīng)該主流程都正常)

其實(shí)和其他配置管理頁面差不多帕翻,前端優(yōu)化了一下面包屑,頂部的菜單也放回到左側(cè)了萝风∴值В看看mac下的效果:

這里我給自己本地部署了個(gè)單實(shí)例的redis

搜索選項(xiàng)改動(dòng)了一些壶唤,所見即所得沥匈,如果搜索項(xiàng)發(fā)生變化孤个,那么內(nèi)容也會(huì)隨之切換

關(guān)于Redis客戶端的選用

其實(shí)在這個(gè)問題上我是比較糾結(jié)的彼硫,redis有star很多的py客戶端拢蛋,也有與之對(duì)應(yīng)的集群版本躲胳。但他們并不支持asyncio筐钟。

而支持asyncio的aioredis整吆,本身是個(gè)很好的選擇,但人家沒有支持redis集群的計(jì)劃文狱。orz

所以今天想的是要不就用個(gè)同步的redis-cluster-py庫算了粥鞋,不過在我翻了github一段時(shí)間,發(fā)現(xiàn)了個(gè)叫aredis的異步庫瞄崇。大概瞅了下呻粹,他基本上是保持了和redis-cluster-py接近的api,可能也是為了吸引用戶苏研。

所以咱們就先試驗(yàn)一下等浊,小白鼠嘛,總得有人來做摹蘑。

安裝aredis

看官網(wǎng)是要安裝aredis[hiredis]筹燕,但我好像不適合這樣方式,于是我分開裝:

pip3 install aredis hiredis

編寫RedisManager

其實(shí)這里還是和MySQL比較接近的衅鹿,也是通過一個(gè)字典存放各個(gè)redis的連接配置撒踪。

不過由于Redis的集群和單實(shí)例還有一點(diǎn)區(qū)別(好在我們編寫配置的時(shí)候就準(zhǔn)備好了),所以我們最好是針對(duì)單實(shí)例和集群分別編寫2個(gè)map存放他們的client大渤,當(dāng)然1個(gè)也是ok的制妄。

整體流程: 從字典獲取客戶端,如果沒有則新開一個(gè)客戶端泵三,并放入緩存耕捞,有則返回。

  • 可能存在的問題

    代碼不是線程安全的烫幕,需要觀察是否需要加鎖

    緩存不像LRU會(huì)降頻俺抽,也不能自動(dòng)過期

    對(duì)我來說第一個(gè)肯定是個(gè)大問題,如果出現(xiàn)了就必須得解決较曼。至于第二個(gè)問題磷斧,由于redis配置很少變動(dòng),而且我們本身是連接池的形式捷犹,所以影響不算大弛饭。

    話不多說,現(xiàn)在我們就來編寫吧:

"""
redis客戶端伏恐,基于aredis(支持集群孩哑,aioredis不支持集群)
"""
from aredis import StrictRedisCluster, ClusterConnectionPool, ConnectionPool, StrictRedis

from app.excpetions.RedisException import RedisException


class PityRedisManager(object):
    """非線程安全栓霜,可能存在問題
    """
    _cluster_pool = dict()
    _pool = dict()

    @staticmethod
    def get_cluster_client(redis_id: int, addr: str):
        """
        獲取redis集群客戶端
        :param redis_id:
        :param addr:
        :return:
        """
        cluster = PityRedisManager._cluster_pool.get(redis_id)
        if cluster is not None:
            return cluster
        client = PityRedisManager.get_cluster(addr)
        PityRedisManager._cluster_pool[redis_id] = client
        return client

    @staticmethod
    def get_single_node_client(redis_id: int, addr: str, password: str, db: str):
        """
        獲取redis單實(shí)例客戶端
        :param redis_id:
        :param addr:
        :param password:
        :param db:
        :return:
        """
        node = PityRedisManager._cluster_pool.get(redis_id)
        if node is not None:
            return node
        host, port = addr.split(":")
        pool = ConnectionPool(host=host, port=port, db=db, max_connections=100, password=password,
                              decode_responses=True)
        client = StrictRedis(connection_pool=pool)
        PityRedisManager._pool[redis_id] = PityRedisManager.get_cluster(addr)
        return client

    @staticmethod
    def refresh_redis_client(redis_id: int, addr: str, password: str, db: str):
        """
        刷新redis客戶端
        :param redis_id:
        :param addr:
        :param password:
        :param db:
        :return:
        """
        host, port = addr.split(":")
        pool = ConnectionPool(host=host, port=port, db=db, max_connections=100, password=password,
                              decode_responses=True)
        client = StrictRedis(connection_pool=pool, decode_responses=True)
        PityRedisManager._pool[redis_id] = client

    @staticmethod
    def refresh_redis_cluster(redis_id: int, addr: str):
        PityRedisManager._cluster_pool[redis_id] = PityRedisManager.get_cluster(addr)

    @staticmethod
    def get_cluster(addr: str):
        """
        獲取集群連接池
        :param addr:
        :return:
        """
        try:
            nodes = addr.split(',')
            startup_nodes = [{"host": n.split(":")[0], "port": n.split(":")[1]} for n in nodes]
            pool = ClusterConnectionPool(startup_nodes=startup_nodes, max_connections=100, decode_responses=True)
            client = StrictRedisCluster(connection_pool=pool, decode_responses=True)
            return client
        except Exception as e:
            raise RedisException(f"獲取Redis連接失敗, {e}")

我們以數(shù)據(jù)庫的唯一id為key翠桦,緩存redis的連接池

由于連接池會(huì)自動(dòng)開啟/關(guān)閉連接,所以我們不需要手動(dòng)關(guān)閉客戶端销凑,非常方便丛晌。

仔細(xì)看看redis執(zhí)行command的方法,里面會(huì)開辟連接斗幼,最終關(guān)閉連接澎蛛,這就是連接池的好處,連接不會(huì)過期蜕窿,因?yàn)槊看味际切芦@取的

可以明顯看到我們分別用了ClusterConnectionPool和ConnectionPool谋逻,分別對(duì)應(yīng)集群和實(shí)例。參數(shù)基本上算是一致桐经。

至于refresh毁兆,是給改動(dòng)redis以后做的刷新連接的工作。

以上就是RedisManager的內(nèi)容阴挣,到這只是能夠獲取Redis客戶端了气堕。

嘗試一下

有條件的同學(xué)可以本次安裝redis:

$ wget https://download.redis.io/releases/redis-6.2.6.tar.gz
$ tar xzf redis-6.2.6.tar.gz
$ cd redis-6.2.6
$ make

make了以后,修改redis-6.2.6目錄下的redis.conf, 接著取消這一行的注釋:

image

使用密碼模式(redis最好是加密碼畔咧,端口號(hào)也盡量不要用原生的6379茎芭,本寶寶有臺(tái)機(jī)器被人通過redis植入了挖礦程序,苦不堪言

  • 在redis-6.2.6目錄下啟動(dòng)
src/redis-server redis.conf

這樣本地redis的實(shí)例就啟動(dòng)了~

image

編寫個(gè)在線測(cè)試redis的接口

image
  • 先通過id拿到redis的配置信息

  • 然后通過manager拿到連接池

  • 對(duì)redis發(fā)動(dòng)命令

    我們?cè)?a target="_blank">http://localhost:7777/docs打開swagger調(diào)試:

  • 讀取faker

image
  • 設(shè)置faker為s12
image
  • 再次取faker
image

可以看到redis的相關(guān)操作已經(jīng)是可以用了誓沸,那我們今天的內(nèi)容就到這了梅桩,愉快的周末總是辣么短暫

下一節(jié)我們就得編寫在線執(zhí)行Redis的命令及相關(guān)頁面了蔽介!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末摘投,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子虹蓄,更是在濱河造成了極大的恐慌犀呼,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件薇组,死亡現(xiàn)場(chǎng)離奇詭異外臂,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)律胀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門宋光,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人炭菌,你說我怎么就攤上這事罪佳。” “怎么了黑低?”我有些...
    開封第一講書人閱讀 169,421評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵赘艳,是天一觀的道長(zhǎng)酌毡。 經(jīng)常有香客問我,道長(zhǎng)蕾管,這世上最難降的妖魔是什么枷踏? 我笑而不...
    開封第一講書人閱讀 60,114評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮掰曾,結(jié)果婚禮上旭蠕,老公的妹妹穿的比我還像新娘。我一直安慰自己旷坦,他們只是感情好掏熬,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秒梅,像睡著了一般孽江。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上番电,一...
    開封第一講書人閱讀 52,713評(píng)論 1 312
  • 那天岗屏,我揣著相機(jī)與錄音,去河邊找鬼漱办。 笑死这刷,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的娩井。 我是一名探鬼主播暇屋,決...
    沈念sama閱讀 41,170評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼洞辣!你這毒婦竟也來了咐刨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,116評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤扬霜,失蹤者是張志新(化名)和其女友劉穎定鸟,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體著瓶,經(jīng)...
    沈念sama閱讀 46,651評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡联予,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了材原。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沸久。...
    茶點(diǎn)故事閱讀 40,865評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖余蟹,靈堂內(nèi)的尸體忽然破棺而出卷胯,到底是詐尸還是另有隱情,我是刑警寧澤威酒,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布窑睁,位于F島的核電站话告,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏卵慰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評(píng)論 3 336
  • 文/蒙蒙 一佛呻、第九天 我趴在偏房一處隱蔽的房頂上張望裳朋。 院中可真熱鬧,春花似錦吓著、人聲如沸鲤嫡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽暖眼。三九已至,卻和暖如春纺裁,著一層夾襖步出監(jiān)牢的瞬間诫肠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工欺缘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留栋豫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,299評(píng)論 3 379
  • 正文 我出身青樓谚殊,卻偏偏與公主長(zhǎng)得像丧鸯,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嫩絮,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容