溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

python學習之redis編程

發(fā)布時間:2020-04-07 21:37:31 來源:網(wǎng)絡(luò) 閱讀:268 作者:霍金181 欄目:編程語言

Redis簡介

Redis(Remote Dictionary Server)遠程字典數(shù)據(jù)服務(wù)的縮寫,由意大利
人開發(fā)的是一款內(nèi)存高速緩存數(shù)據(jù)庫。使用ANSI C語言編寫、支持網(wǎng)絡(luò)、可基于內(nèi)
存亦可持久化的日志型、Key-Value數(shù)據(jù)庫,并提供多種語言的API并提供多種語言
的 API的非關(guān)系型數(shù)據(jù)庫
python學習之redis編程
Redis和Memcache對比?
python學習之redis編程

Redis的安裝

  1. 首先上官網(wǎng)下載Redis 壓縮包,地址 http://redis.io/download
  2. 壓縮包執(zhí)行解壓操作并進行編譯
    #tar xzf redis-x.x.x.tar.gz
    #cd redis-x.x.x/
    #make && make install
    #sh utils/install_server.sh
    Redis的部署
  3. 執(zhí)行Redis-server 命令,啟動Redis 服務(wù)
    redis-server
  4. 客戶端redisClient
    redis-cli
    #登錄redis

    set 'a' '123'

  5. 當添加鍵值后,發(fā)現(xiàn)在當前運行的目錄下,創(chuàng)建了一個文件:dump.rdb,這個文
    件用于將數(shù)據(jù)持久化存儲
    python學習之redis編程

    Redis內(nèi)置數(shù)據(jù)類型

    ? string 類型 是二進制安全的??梢园魏螖?shù)據(jù)(eg: jpg 圖片或者序列化的對象)。
    從內(nèi)部實現(xiàn)來看其實 string 可以看作 byte 數(shù)組,最大上限是 1G 字節(jié)。
    ? hash類型 是一個 string 類型的 field 和 value 的映射表.它的添加、刪除操作都是
    O(1)(平均)。
    ? list類型 是一個 string 類型的雙向鏈表。最大長度是(2 32 )。
    ? set 類型 是 string 類型的通過 hash table 實現(xiàn)的無序集合。添加、刪除和查找的復
    雜度都是 O(1)。最大長度是(2 32 )。
    Redis內(nèi)置指令: http://doc.redisfans.com/
    python學習之redis編程 python學習之redis編程
    Redis應(yīng)用場景
    python學習之redis編程

    Redis持久化

    Redis 是一個內(nèi)存數(shù)據(jù)庫,與傳統(tǒng)的MySQL,Oracle等關(guān)系型數(shù)據(jù)庫直接將內(nèi)容保存到硬盤
    中相比,內(nèi)存數(shù)據(jù)庫的讀寫效率比傳統(tǒng)數(shù)據(jù)庫要快的多(內(nèi)存的讀寫效率遠遠大于硬盤的讀寫
    效率)。但是保存在內(nèi)存中也隨之帶來了一個缺點,一旦斷電或者宕機,那么內(nèi)存數(shù)據(jù)庫中的
    數(shù)據(jù)將會全部丟失。
    目標: 持久化就是把內(nèi)存的數(shù)據(jù)寫到磁盤中去,防止服務(wù)宕機了內(nèi)存數(shù)據(jù)丟失。
    Redis 提供了兩種持久化方式:RDB(默認) 和AOF
    Redis持久化: RDB
    RDB是Redis用來進行持久化的一種方式,是把當前內(nèi)存中的數(shù)據(jù)集快照寫入
    磁盤,也就是 Snapshot 快照(數(shù)據(jù)庫中所有鍵值對數(shù)據(jù))。恢復時是將快
    照文件直接讀到內(nèi)存里。
    python學習之redis編程

    Redis持久化: RDB

    我們可以配置 redis在 n 秒內(nèi)如果超過 m 個 key 被修改就自動做快照,下面是默認的快照保
    存配置:
    dbfilename dump.rdb
    save 900 1
    save 300 10
    #持久化存儲文件名為 dump.rdb
    #900 秒內(nèi)如果超過 1 個 key 被修改,則發(fā)起快照保存
    #300 秒內(nèi)容如超過 10 個 key 被修改,則發(fā)起快照保

    save 60 10000 # 600 秒內(nèi)容如超過 10000 個 key 被修改,則發(fā)起快照保存
    Redis持久化: AOF
    ? RDB 持久化存是一定時間內(nèi)做一次備份,如果
    redis意外down掉的話,就會丟失最后一次快照后
    的所有修改(數(shù)據(jù)有丟失)。
    ? 工作原理: 當 redis 重啟時會通過重新執(zhí)行文件中
    保存的寫命令來在內(nèi)存中重建整個數(shù)據(jù)庫的內(nèi)容。python學習之redis編程

    Redis持久化: AOF

    通過配置文件告訴 redis 我們想要通過 fsync 函數(shù)強制 os 寫入到磁盤的時機。有三
    種方式如下(默認是:每秒 fsync 一次), 通過BGREWRITEAOF指令壓縮/優(yōu)化命令
    //啟用 aof 持久化方式
    appendonly yes
    //收到寫命令就立即寫入磁盤,最慢,但是保證完全的持久化
    #appendfsync always
    //每秒鐘寫入磁盤一次,在性能和持久化方面做了很好的折中
    appendfsync everysec
    //完全依賴 os,性能最好,持久化沒保證
    #appendfsync no
    配置:修改redis配置文件
    vim /etc/redis/6379.conf
    appendonly yes #修改appendonly為yes
    cd /var/lib/redis/6379/ #進入目錄生成aof文件
    ls
    appendonly.aof dump.rdb
    python批量插入數(shù)據(jù)發(fā)現(xiàn)appendonly.aof文件大小發(fā)生變化

import  redis
redis_client = redis.StrictRedis(host='localhost',port=6379)
redis_client.mset({'name':'westos','age':10})
name = redis_client.get('name').decode('utf-8')
name_len = redis_client.strlen('name')
print('用戶名稱:',name,'用戶名長度:',name_len)
age_add = redis_client.incr('age')
for i in range(1000):
    redis_client.incr('age')

Redis架構(gòu)模式

單機版
特點:簡單
問題:1、內(nèi)存容量有限 2、處理能力有限 3、無法高可用。
python學習之redis編程
主從復制
python學習之redis編程
主從復制
Redis 的復制(replication)功能允許用戶根據(jù)一個 Redis 服務(wù)器來創(chuàng)建任意多個該
服務(wù)器的復制品,其中被復制的服務(wù)器為主服務(wù)器(master),而通過復制創(chuàng)建出來
的服務(wù)器復制品則為從服務(wù)器(slave)。 只要主從服務(wù)器之間的網(wǎng)絡(luò)連接正常,主從
服務(wù)器兩者會具有相同的數(shù)據(jù),主服務(wù)器就會一直將發(fā)生在自己身上的數(shù)據(jù)更新同步 給
從服務(wù)器,從而一直保證主從服務(wù)器的數(shù)據(jù)相同。
特點:
1、master/slave 角色
2、master/slave 數(shù)據(jù)相同
3、降低 master 讀壓力在轉(zhuǎn)交從庫
問題:

  1. 無法保證高可用
  2. 沒有解決 master 寫的壓力
    Python與Redis
    python學習之redis編程
    python學習之redis編程
    封裝
    ? 連接redis服務(wù)器部分是一致的
    ? 將string類型的讀寫進行封裝
    python學習之redis編程

python學習之redis編程
"""

01_Redis數(shù)據(jù)結(jié)構(gòu).py

import redis

redis_client = redis.StrictRedis(host='172.25.254.18', port=6379)

#對于字符串的操作
"""
get
mget
set 
mset
incr
incrby
decr 
decrby
strlen
"""
redis_client.mset({'name':'westos', 'age':10})
name = redis_client.get('name').decode('utf-8')
name_len = redis_client.strlen('name')
print("用戶名稱: ", name, "用戶名稱長度: ", name_len)
age_add = redis_client.incr('age')
print("當前年齡為: ", redis_client.get('age'))
for i in range(10000):
    redis_client.incr('age')

限制某段時間內(nèi)的訪問次數(shù),就比如我們登錄的功能可以用手機獲取驗證碼登錄,但是我們發(fā)送驗證碼使用的第三方,是多少錢多少條的,
肯定不能讓他一直點,一直發(fā)短信,就算前端js做了校驗,若有些人用fiddler攔截繞過前臺就麻煩了,
這時候可以用redis的incr命令和expire結(jié)合起來做一個解決方案

  1. 用戶請求了我們的發(fā)送短信驗證碼服務(wù), 用戶對應(yīng)的key(電話號碼)
  2. 如果緩存中存在了,就是已經(jīng)請求過驗證碼了,比如我系統(tǒng)參數(shù)設(shè)置的至少60秒發(fā)送一次短信, 那就代表60之內(nèi)再次請求了,返回False阻止
  3. 否則就是第一次請求短信驗證碼或者等了60再次請求的驗證碼, 發(fā)送驗證碼. 放入redis緩存并設(shè)置失效時間60秒
import time

def send_msg(phone):
    """模擬給手機發(fā)送驗證碼"""
    import string
    import random
    #['4', '1', '5', '9']
    nums_list = random.sample(string.digits, 4)
    nums_code = "".join(nums_list)
    print("%s驗證碼:%s[公司]" %(phone, nums_code))
    return  nums_code

def phone_code(phone):
    """
    電話驗證碼模擬, 3秒之后可以再次發(fā)送驗證碼
    :param phone:
    :return:
    """
    import redis
    client = redis.StrictRedis()
    #可以從緩存中查詢驗證碼已經(jīng)發(fā)送。
    if client.get(phone):
        print("驗證碼發(fā)送頻繁, 請稍后再試")
        return  False
    else:
        code = send_msg(phone)
        client.set(phone, code, 3)
        print("發(fā)送驗證碼成功")

if __name__ == '__main__':
    print("第一次發(fā)送")
    phone_code('110')
    print("第二次發(fā)送")
    phone_code('110')
    time.sleep(4)
    print("第三次發(fā)送")
    phone_code('110')"""
IP限制頻繁訪問:
    如果你運行 HTTP 服務(wù),并且希望限制 HTTP 的訪問頻率,那么你可以借助一些比較穩(wěn)定的工具,
    例如: github.com/didip/tollbooth。不過如果你構(gòu)建的應(yīng)用比較簡單,也可以自己來實現(xiàn)。
IP限制的規(guī)則:
    每分鐘訪問次數(shù)不能超過60次。
"""

def ip_limit(IP):
    """
    每分鐘訪問次數(shù)不能超過60次。
    key: value = IP:count
    :param IP:
    :return:
    """
    import redis
    client = redis.StrictRedis()
    #1). 判斷是否訪問過本服務(wù)器;
    if client.exists(IP):
        count = client.get(IP).decode('utf-8')
        if int(count) >= 60:
            print("%s訪問頻繁" %(IP))
        else:
            client.incr(IP)
            print("訪問+1")
    else:
        client.set(IP, 1, 60)
        print("%s第一次訪問" %(IP))

if __name__ == '__main__':
    ip_limit('127.0.0.1')
    for i in range(100):
        ip_limit('172.25.254.197')

"""

02_Redis數(shù)據(jù)結(jié)構(gòu)列表.py

Redis: 內(nèi)存緩存數(shù)據(jù)庫, 消息隊列(kafka、RabbitMQ)
#如何實現(xiàn)高并發(fā)場景下?lián)尲t包的設(shè)計。

import  queue

class RedisQueue(object):
    """左邊為隊頭, 右邊為隊尾的消息隊列"""
    def __init__(self, name, **conf):
        import redis
        self.__client = redis.Redis(**conf)
        self.key = name

    def qsize(self):
        return  self.__client.llen(self.key)

    def put(self, item):
        """入隊操作"""
        self.__client.rpush(self.key, item)

    def get(self, timeout=5):
        """獲取對頭, 如果沒有到, 等待時間為timeout"""
        item = self.__client.blpop(self.key, timeout=timeout)
        return  item

    def get_nowait(self):
        item = self.__client.blpop(self.key)
        return  item

if __name__ == '__main__':
    q = RedisQueue('scores', host='172.25.254.18', port=6380)
    for i in range(10):
        q.put(i)

    while True:
        result = q.get(timeout=100)
        print(result)
        if not result:
            break

06_集合與有序集合.py


項目實戰(zhàn): 分布式緩存服務(wù)實踐: Redis實現(xiàn)排行榜功能
在網(wǎng)頁和APP中常常需要用到榜單的功能,對某個key-value的列表進行降序顯示。當操作和查詢并發(fā)大的時候,
使用傳統(tǒng)數(shù)據(jù)庫就會遇到性能瓶頸,造成較大的時延。使用分布式緩存服務(wù)Redis,可以實現(xiàn)一個
商品熱銷排行榜的功能。它的優(yōu)勢在于:
    - 數(shù)據(jù)保存在緩存中,讀寫速度非???。
    - 提供字符串(String)、鏈表(List)、集合(Set)、哈希(Hash)等多種數(shù)據(jù)結(jié)構(gòu)類型的存儲。

"""
import random

def productSalesRankDemo():
    import redis
    import uuid
    PRODUCT_KINDS = 30
    host = "127.0.0.1"
    port = 6379
    password = ''
    key = "商品熱銷排行榜"
    client = redis.StrictRedis(host=host, port=port, password=password)
    if not client.exists(key):
        products = {}
        for count in range(PRODUCT_KINDS):
            product_name = 'product-' + str(uuid.uuid4())
            product_sale = random.randint(1000, 20000)
            products[product_name] = product_sale
        client.zadd(key, products)

productSalesRankDemo()"""

07_管道pipeline優(yōu)化程序.py

import redis

redis_client = redis.StrictRedis(host='172.25.254.18', port=6380)
pipe = redis_client.pipeline()
pipe.set('name', 'westos')
pipe.set('name', 'westos')
pipe.set('name', 'westos')
pipe.set('name', 'westos')
pipe.set('name', 'westos')
pipe.execute()
"""

08_發(fā)送郵件.py

#設(shè)置服務(wù)器,用戶名、口令以及郵箱的后綴
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr

smtp_server = "smtp.163.com"
from_username = '技術(shù)中心'
mail_user = "xc@163.com"
#是開啟smtp的授權(quán)嗎不是真實的密碼。
mail_password = "westos123"
#郵件主題的前綴
mail_prefix = "[運維開發(fā)部]-"

def send_email(to_addrs, subject, msg):
    try:
        # 將要發(fā)送的文本信息做MIME封裝
        msg = MIMEText(msg)
        #格式化發(fā)件人名稱
        msg['From'] = formataddr([from_username, mail_user])
        msg['To'] = to_addrs
        msg['Subject'] = mail_prefix + subject

        #1. 實例化smtp對象
        server = smtplib.SMTP()
        #2. 連接郵件服務(wù)器
        server.connect(smtp_server)
        #3. 登錄
        server.login(mail_user, mail_password)
        #4. 發(fā)送郵件內(nèi)容
        server.sendmail(mail_user, to_addrs, msg.as_string())
        #5. 關(guān)閉連接
        server.quit()
    except Exception as  e:
        print(str(e))
        return False
    else:
        return True

if __name__ == '__main__':
    send_email('976131@qq.com','寒假作業(yè)', '請與3月2日之前提交')
    print("發(fā)送成功.....")
向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI