Redis安裝、說明、Python中使用

Redis安裝與簡單使用

Redis說明

  • redis是徹底開源免費的,遵照BSD協議,是一個高性能的key-value數據庫

redis特色

  • Redis 支持數據的持久化,能夠將內存中的數據保存在磁盤中,重啓的時候能夠再次加載並使用
  • redis支持五種數據類型 字符串(String) 哈希(hash) 列表(list) 集合(set) 有序集合(sorted sets)
  • Redis 支持數據庫備份

Redis的優點

  • Redis性能極高,讀的速度是110000次/s,寫的速度是81000次/s
  • Redis豐富的數據類型 五種
  • Redis的全部操做都具備原子性
    • 原子性是指一個操做是不可中斷的,要麼所有執行成功要麼所有執行失敗,有着「同生共死」的感受。及時在多個線程一塊兒執行的時候,一個操做一旦開始,就不會被其餘線程所幹擾
  • Redis有豐富的特性,支持publish/subscribe,通知,key過時等待特性

五種數據類型

Redis 數據類型python

    -- String 字符串git

      -- redis的string能夠包含任何數據,包括圖片以及序列化的對象,一個鍵最大能存儲512MB。github

    -- Hash 哈希redis

      -- redis的hash是一個String類型的key和value的映射表,hash特別適合存儲對象,類比python字典。數據庫

    -- List 列表windows

      -- redis的list是簡單的字符串列表,按照插入順序排序,能夠從兩端進行添加,相似於雙向鏈表,列表還能夠進行阻塞。緩存

    -- Set 集合服務器

      -- redis的set是字符串類型的無序且不重複集合。集合是經過哈希表實現的,因此添加,刪除,查找的時間複雜度都是O(1)。app

    -- Zset 有序集合tcp

      -- redis的zset和set同樣,不一樣的是每一個元素都會關聯一個double類型的分數,redis正是經過對分數的排序對集合進行有序存儲。

Redis在widows上安裝

  • 在其它版本下載,百度,網上資料多

1. 下載:

2.啓用

  • 打開一個 cmd 窗口 使用cd命令切換目錄到 C:\redis 運行

    redis-server.exe redis.windows.conf
  • 若是想方便的話,能夠把 redis 的路徑加到系統的環境變量裏,這樣就免得再輸路徑了,後面的那個 redis.windows.conf 能夠省略,若是省略,會啓用默認的。輸入以後,會顯示以下界面

    Redis 安装

  • 這時候另啓一個cmd窗口,原來的不要關閉,否則就沒法訪問服務端了。

  • 切換到redis目錄下運行 redis-cli.exe -h 127.0.0.1 -p 6379

  • 設置鍵值對 set myKey abc

  • 取出鍵值對 get myKey

    Redis 安装

在Python上使用redis

一 Python鏈接redis

  • 參數:decode_responses=True 表示存儲的數據爲字符串類型,默認爲bytes類型
  1. 在Python中安裝redis模塊

    pip3 install redis
  2. 在Python中使用redis

    1. 一次性鏈接(通常不用這個)
    import redis   # 導入redis模塊,經過python操做redis 也能夠直接在redis主機的服務端操做緩存數據庫
    
    r = redis.Redis(host='localhost', port=6379, decode_responses=True)   # host是redis主機,須要redis服務端和客戶端都啓動 redis默認端口是6379, decode_responses=True 表示存儲的數據爲字符串類型,默認爲bytes類型
    r.set('name', 'junxi')  # key是"foo" value是"bar" 將鍵值對存入redis緩存
    print(r['name'])
    print(r.get('name'))  # 取出鍵name對應的值
    print(type(r.get('name')))
    1. 鏈接池(重要

    當程序建立數據源實例是,系統會一次性建立多個數據庫鏈接,並把這些數據庫鏈接保存在鏈接池中,當程序須要進行對數據庫訪問時,無需從新新建數據庫鏈接,而是從鏈接池中取出一個空閒的數據庫鏈接

    import redis    # 導入redis模塊,經過python操做redis 也能夠直接在redis主機的服務端操做緩存數據庫
    
    pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)   # host是redis主機,須要redis服務端和客戶端都起着 redis默認端口是6379
    r = redis.Redis(connection_pool=pool)
    r.set('gender', 'male')     # key是"gender" value是"male" 將鍵值對存入redis緩存
    print(r.get('gender'))      # gender 取出鍵male對應的值

二 redis基本命令String

  • set(name, value, ex=None, px=None, nx=False, xx=False)

  • 在Redis中設置值,默認,不存在則建立,存在即修改

  • 參數

    • ex,過時時間(秒)
    • px,過時時間(毫秒)
    • nx,若是設置爲True,則只有name不存在時,當前set操做才執行
    • xx,若是設置爲True,則只有name存在時,當前set操做才執行
  • 實例演示:

  • ex,過時時間(秒) 這裏過時時間是3秒,3秒後p,鍵food的值就變成None

    import redis
    pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
    r = redis.Redis(connection_pool=pool)
    r.set('food', 'mutton', ex=3)    # key是"food" value是"mutton" 將鍵值對存入redis緩存, ex=3表示3秒後food對應的value爲none,
    print(r.get('food'))  # mutton 取出鍵food對應的值
  • nx,若是設置爲True,則只有name不存在時,當前set操做才執行 (新建)

    import redis
    
    pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
    r = redis.Redis(connection_pool=pool)
    print(r.set('fruit', 'watermelon', nx=True))    # True--不存在
    # 若是鍵fruit不存在,那麼輸出是True;若是鍵fruit已經存在,輸出是None
  • setnx(name, value)

    • 設置值,只有name不存在時,執行設置操做(添加)

      print(r.setnx('fruit1', 'banana'))  # fruit1不存在,輸出爲True
  • setex(name, value, time)

    • 參數: time ,過時時間,(數字秒或timedelalta對像

      import redis
      import time
      
      pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
      r = redis.Redis(connection_pool=pool)
      r.setex("fruit2", "orange", 5)
      print(r.get('fruit2'))  # 5秒後,取值就從orange變成None
  • psetex(name, time_ms, value)

    • 參數: time_ms,過時時間(數字毫秒或 timedelta對象

      r.psetex("fruit3", 5000, "apple")
      time.sleep(5)
      print(r.get('fruit3'))  # 5000毫秒後,取值就從apple變成None

批量設置值 mset(*args, **kwargs)

  • 批量設置值

    r.mget({'k1': 'v1', 'k2': 'v2'})
    r.mset(k1="v1", k2="v2") # 這裏k1 和k2 不能帶引號 一次設置對個鍵值對
    print(r.mget("k1", "k2"))   # 一次取出多個鍵對應的值
    print(r.mget("k1"))

批量取值 mget(key, *args)

  • 批量取值

    print(r.mget('k1', 'k2'))
    print(r.mget(['k1', 'k2']))
    print(r.mget("fruit", "fruit1", "fruit2", "k1", "k2"))  # 將目前redis緩存中的鍵對應的值批量取出來
  • getset(name, value)

    • 設置新值,並取出原來的值

      print(r.getset("food", "barbecue"))  # 設置的新值是barbecue 設置前的值是beef
  • getrange(key, start, end)

  • 獲取子序列(根據字節獲取,非字符)

  • 參數:

    name, redis的key

    start: 啓始位置(字節)

    end:結束位置(字節)

    如: "騎士" , 0-3表示 騎

    r.set("cn_name", "東方月初") # 漢字
    print(r.getrange("cn_name", 0, 2).decode('utf8'))   # 取索引號是0-2 前3位的字節 東 切片操做 (一個漢字3個字節 1個字母一個字節 每一個字節8bit)
    print(r.getrange("cn_name", 0, -1))  # 取全部的字節 東方月初 切片操做
    r.set("en_name","junxi") # 字母
    print(r.getrange("en_name", 0, 2))  # 取索引號是0-2 前3位的字節 jun 切片操做 (一個漢字3個字節 1個字母一個字節 每一個字節8bit)
    print(r.getrange("en_name", 0, -1)) # 取全部的字節 junxi 切片操做
  • setrange(name, offset, value) (沒看懂)

    • 修改字符串內容,從指定字符安串索引開始向後替換(若是新值比原值長,沒法添加)

    • 參數:

      offset 字符串的索引,字節(一個漢字三個字節,索引是從0開始的

      value 值只是是1 或 0

      注:若是在Redis中有一個對應: n1 = "foo",
      那麼字符串foo的二進制表示爲:01100110 01101111 01101111
      因此,若是執行 setbit('n1', 7, 1),則就會將第7位設置爲1,
      那麼最終二進制則變成 01100111 01101111 01101111,即:"goo"
      
      擴展,轉換二進制表示:
      source = "陳思惟"
      source = "foo"
      for i in source:
      num = ord(i)   # ord方法返回單字符字符串的Unicode編碼點
      print bin(num).replace('b','')
      特別的,若是source是漢字 "陳思惟"怎麼辦?
      答:對於utf-8,每個漢字佔 3 個字節,那麼 "陳思惟" 則有 9個字節
      對於漢字,for循環時候會按照 字節 迭代,那麼在迭代時,將每個字節轉換 十進制數,而後再將十進制數轉換成二進制
      11100110 10101101 10100110 11100110 10110010 10011011 11101001 10111101 10010000
  • gitbit(name, offset)

    • 獲取name對應的值的二進制表示中的某位值(0 或者1)

      print(r.getbit("foo1", 0)) # 0 foo1 對應的二進制 4個字節 32位 第0位是0仍是1
  • bitcount(key, start=None, end=None) 瞭解

    • 獲取name對應的二進制表示中1的個數

    • 參數

      key redis的name

      start 字節啓始位置

      end 字節結束位置

      print(r.get("foo"))  # goo1 01100111
      print(r.bitcount("foo",0,1))  # 11 表示前2個字節中,1出現的個數

    三 redis基本命令hash

  • hset(name, key, value)  增長單個 不存在則建立
    
      hget(name, key)  獲取單個
    
      hmset(name, mapping)  批量增長 mapping爲字典
    
      hgetall(name) 獲取name對應hash的全部鍵值
    
      hlen(name)  獲取name對應的hash中鍵值對的個數
    
      hkeys(name)  獲取name對應的hash中全部的key的值
    
      hvals(name)  獲取name對應的hash中全部的value的值
    
      hexists(name, key)  檢查name對應的hash是否存在當前傳入的key
    
      hdel(name,*keys)   將name對應的hash中指定key的鍵值對刪除
    
      hscan_iter(name, match=None, count=None)
        利用yield封裝hscan建立生成器,實現分批去redis中獲取數據
        參數:
        match,匹配指定key,默認None 表示全部的key
        count,每次分片最少獲取個數,默認None表示採用Redis的默認分片個數
  • 單個增長--修改(單個取出)--沒有就新增,有的話就修改
    hset(name, key, value)
    name對應的hash中設置一個鍵值對(不存在,則建立;不然,修改)
    參數:
    name,redis的name
    key,name對應的hash中的key
    value,name對應的hash中的value
    注:
    hsetnx(name, key, value),當name對應的hash中不存在當前key時則建立(至關於添加)

import redis
  import time
  
  pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
  r = redis.Redis(connection_pool=pool)
  
  r.hset("hash1", "k1", "v1")
  r.hset("hash1", "k2", "v2")
  print(r.hkeys("hash1")) # 取hash中全部的key
  print(r.hget("hash1", "k1"))    # 單個取hash的key對應的值
  print(r.hmget("hash1", "k1", "k2")) # 多個取hash的key對應的值
  r.hsetnx("hash1", "k2", "v3") # 只能新建
  print(r.hget("hash1", "k2"))

四 redis的命令 list

lpush(name,values)  在name對應的list中左邊添加元素 沒有就新建

  llen(name) 獲取name對應的列表長度

  lrang(name, index1, index2) 按照index切片取出name對應列表裏值

  lpushx(name, value)  只能添加不能新建

  linsert(name, where, refvalue, value))  

    在name對應的列表的某一個值前或後插入一個新值
    參數:
    name,redis的name
    where,BEFORE或AFTER
    refvalue,標杆值,即:在它先後插入數據
    value,要插入的數據 

  lset(name, index, value)  給指定索引修改值

  lrem(name, value, num)

    在name對應的list中刪除指定的值
    參數:
    name,redis的name
    value,要刪除的值
    num, num=0,刪除列表中全部的指定值;
    num=2,從前到後,刪除2個; num=1,從前到後,刪除左邊第1個
    num=-2,從後向前,刪除2個

  lindex(name, index)  在name對應的列表中根據索引獲取列表元素

五 redis的發佈者訂閱者模式

  • redis的發佈和訂閱模式就像是廣播發消息同樣,只要一發部,訂閱者就能接收到

redis發佈者

import redis

r = redis.Redis(host="127.0.0.1", password="", decode_responses=True)

r.publish("name", "dongfangyuechu")

訂閱者

import redis

r = redis.Redis(host="127.0.0.1", password="", decode_responses=True)

# 第一步 生成一個訂閱者對象
pubsub = r.pubsub()
# 第二步 訂閱一個消息 實際上就是監聽這個鍵
pubsub.subscribe("name")

# 第三步 死循環一直等待監聽結果
while True:
    print("working~~~")
    msg = pubsub.parse_response()
    print(msg)

六 管道/事物(pileline)

  • redis 默認在執行每次請求都會建立(鏈接池申請鏈接)和斷開(歸還鏈接池) 一次鏈接操做

  • 若是想要在一次請求中指定多個命令,則可使用管道(pipline)實現一次請求指定多個命令,而且默認狀況下一次piplilne是原子性操做

  • 單個 Redis 命令的執行是原子性的,但 Redis 沒有在事務上增長任何維持原子性的機制,因此 Redis 事務的執行並非原子性的。

    事務能夠理解爲一個打包的批量執行腳本,但批量指令並不是原子化的操做,中間某條指令的失敗不會致使前面已作指令的回滾,也不會形成後續的指令不作

  • 管道:是redis在提供單個請求中緩衝多條服務器命令基類的子類,它經過減小服務器-客戶端之間反覆的tcp數據庫包,從而大大提升了執行批量命令的功能

    import redis
    import time
    
    pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True)
    r = redis.Redis(connection_pool=pool)
    
    # pipe = r.pipeline(transaction=False)    # 默認的狀況下,管道里執行的命令能夠保證執行的原子性,執行pipe = r.pipeline(transaction=False)能夠禁用這一特性。
    # pipe = r.pipeline(transaction=True)
    pipe = r.pipeline() # 建立一個管道
    
    pipe.set('name', 'jack')
    pipe.set('role', 'sb')
    pipe.sadd('faz', 'baz') # 新增
    pipe.incr('num')    # 若是num不存在則vaule爲1,若是存在,則value自增1
    pipe.execute()
    
    print(r.get("name"))
    print(r.get("role"))
    print(r.get("num"))

    管道的命令能夠寫在一塊兒

    pipe.set('hello', 'redis').sadd('faz', 'baz').incr('num').execute()
    print(r.get("name"))
    print(r.get("role"))
    print(r.get("num"))

本文參考,更加詳細請看:https://www.jianshu.com/p/2639549bedc8

相關文章
相關標籤/搜索