Redis 數據庫

1、redis的概述和安裝

 

1. redis概述

1.1 redis是什麼

1Redis:REmote DIctionary Server(遠程字典服務器)html

 

2)是徹底開源免費的,用C語言編寫的,遵照BSD開源協議,python

是一個高性能的(key/value)分佈式內存數據庫,基於內存運行,mysql

並支持持久化的NoSQL數據庫,是當前最熱門的NoSql數據庫之一,也被人們稱爲數據結構服務器。redis

 

3Redis 與其餘 key - value 緩存產品有如下三個特色:sql

3.1)Redis支持數據的持久化,能夠將內存中的數據保持在磁盤中,重啓的時候能夠再次加載進行使用數據庫

3.2)Redis不只僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲vim

3.3)Redis支持數據的備份,即master-slave模式的數據備份緩存

1.2 能幹嗎

1)內存存儲和持久化:redis支持異步將內存中的數據寫到硬盤上,同時不影響繼續服務安全

2)取最新N個數據的操做,如:能夠將最新的10條評論的ID放在List集合服務器

 

3)模擬相似於HttpSession這種須要設定過時時間的功能

 

4)發佈、訂閱消息系統

 

5)定時器、計數器

2. 安裝redis

2.1. 安裝方式一:使用命令安裝

因爲企業裏面作Redis開發,99%都是Linux版的運用和安裝,

幾乎不會涉及到Windows版。

安裝包括服務端和客戶端

Ubuntu 系統安裝 Redi 可使用如下命令:

sudo apt-get update
sudo apt-get install redis-server

 

啓動 Redis 服務

 

redis-server
或者
sudo redis-server /etc/redis/redis.conf

 

使用 redis 客戶端查看是否啓動

 

redis-cli

 

檢查是否安裝成功

 

127.0.0.1 是本機 IP 6379 redis 服務端口。如今咱們輸入 PING 命令。

以上說明咱們已經成功安裝了redis

2.2. 安裝方式二:使用下載的壓縮包安裝

下載:打開redis官方網站(https://redis.io/),推薦下載穩定版本(stable)

http://www.redis.cn/

 

解壓

tar zxvf redis-3.2.5.tar.gz

複製:推薦放到usr/local目錄下

sudo mv -r redis-3.2.5/* /usr/local/redis/
進入redis目錄
cd /usr/local/redis/

生成

sudo make

測試

sudo make test

這段運行時間會較長

安裝:將redis的命令安裝到/usr/bin/目錄

sudo make install

3. 運行

3.1. 啓動服務器

啓動服務器:在桌面目錄

redis-server
或者
sudo redis-server /etc/redis/redis.conf

按ctrl+c中止

3.2. 啓動客戶端

啓動客戶端:在新終端中運行以下代碼

redis-cli

運行命令

ping
set 'a' '123'

當添加鍵值後,發如今當前運行的目錄下,建立了一個文件:dump.rdb,這個文件用於將數據持久化存儲

4. 查看redis的版本

查看redis的版本有兩種方式:

4 1. 查詢服務端

redis-server --version
 或者
redis-server -v

獲得的結果是:

Redis server v=3.0.6 sha=00000000:0 malloc=jemalloc-3.6.0 bits=64 build=687a2a319020fa42

4.2 查詢客戶端

redis-cli --version 
或者 
redis-cli -v

獲得的結果是:redis-cli 3.0.6
嚴格上說:經過 redis-cli 獲得的結果應該是redis-cli 的版本,可是 redis-cli 和redis-server 通常都是從同一套源碼編譯出的。因此應該是同樣的。

 

2、基本配置

 

1. 查看redis.conf配置文件

在原文件/usr/local/redis目錄下,文件redis.conf爲配置文件

已經移動到/etc/redis/目錄下,文件redis.conf爲配置文件

1.1  綁定地址

打開配置文件命令:sudo subl /etc/redis/redis.conf

綁定地址:若是須要遠程訪問,可將此行註釋

bind 127.0.0.1

1.2  端口,默認爲6379

建議不要修改

port 6379

1.3 守護進程

  • 是否以守護進程運行
    • 若是以守護進程運行,則不會在命令行阻塞,相似於服務
    • 若是以非守護進程運行,則當前終端被阻塞,沒法使用

推薦改成yes,以守護進程運行

daemonize no|yes

 

1.4 數據文件及設置存放位置

數據文件

dbfilename dump.rdb

設置數據文件存儲路徑

dir的默認值爲./,表示當前目錄

推薦改成:dir /var/lib/redis

 

注意,刪除後,插入數據重啓redis服務器才能看到數據庫

 

2. redis基本命令

  • 直接運行redis-server會直接運行,阻塞當前終端
  • 通常配置文件都放在/etc/目錄下
sudo cp /usr/local/redis/redis.conf /etc/redis/

2.1 查看redis當前狀態

ps ajx|grep redis

2.2 啓動redis服務

#推薦指定配置文件啓動

sudo redis-server /etc/redis/redis.conf
或者
sudo service redis start

2.3 中止redis服務

sudo kill -9 redis的進程id
或者
sudo service redis stop

2.4 重啓redis服務

sudo service redis restart

當配置文件從新配置後,通常會重啓服務器這樣配置才生效

 

3、數據操做

rediskey-value的數據,因此每一個數據都是一個鍵值對

鍵的類型是字符串

值的類型分爲五種:

  • 字符串string
  • 哈希hash
  • 列表list
  • 集合set
  • 有序集合zset

數據操做的所有命令,

能夠查看redis中文網站(http://redis.cn/commands.html)

接下來逐個介紹操做各種型的命令

1. string

  • stringredis最基本的類型
  • 最大能存儲512MB數據
  • string類型是二進制安全的,便可覺得任何數據,好比數字、圖片、序列化對象等

 

啓動redis服務

sudo redis-server /etc/redis/redis.conf
或者
sudo service redis start

啓動客戶端:在新終端中運行以下代碼

redis-cli

啓動後效果如圖

 

1.1 設置鍵值

1.1.1 設置鍵值

set key value

1.1.2 設置鍵值及過時時間,以秒爲單位

 

SETEX key seconds value

1.1.3 設置多個鍵值--mset

注意,key和值不加引號也能夠

 

MSET key value [key value ...]
案例:
mset 'key1' 'hello' 'key2' 'world' 

1.2 獲取

1.2.1 根據鍵獲取值,若是不存在此鍵則返回nilget不區分大小寫

根據鍵獲取值,若是不存在此鍵則返回nil,get不區分大小寫也就是說getGET均可以獲得數據

GET key

1.2.2 根據多個鍵獲取多個值--mget

MGET key [key ...]
案例
mget 'key1' 'key2'

1.3 運算

  • 要求:值是數字

1.3.1 key對應的value加1

INCR key

 

1.3.2 key對應的value加整數

INCRBY key increment

 

 

1.3.3 key對應的value減1

DECR key

 

 

1.3.4 key對應的value減整數

DECRBY key decrement

 

 

1.4 其它

1.4.1 追加值

APPEND key value

 

 

1.4.2 獲取值長度

STRLEN key

 

 

2. 鍵的命令

2.1 查找鍵,參數支持正則

KEYS pattern

 

 

 

2.2 判斷鍵是否存在,若是存在返回1,不存在返回0

EXISTS key [key ...]

 

 

2.3 查看鍵對應的value的類型

TYPE key

 

2.4 刪除鍵及對應的值,刪除成功返回1,失敗返回0

DEL key [key ...]

 

 

2.5 設置和查看過時時間,以秒爲單位

爲給定 key 設置生存時間,當 key 過時時(生存時間爲 0 )它會被自動刪除。

能夠對一個已經帶有生存時間的 key 執行 EXPIRE 命令,新指定的生存時間會取代舊的生存時間。沒有過時的是-1,過時的是-2

 

EXPIRE key seconds

 

查看有效時間,以秒爲單位

TTL key

 

 

3. hash

hash用於存儲對象,對象的格式爲鍵值對

hash 特別適合用於存儲對象。相對於將對象的每一個字段存成單個string 類型。將一個對象
存儲在hash 類型中會佔用更少的內存,而且能夠更方便的存取整個對象。省內存的緣由是
新建一個hash 對象時開始是用zipmap(又稱爲small hash)來存儲的。這個zipmap 其實並
不是hash table,可是zipmap 相比正常的hash 實現能夠節省很多hash 自己須要的一些元
數據存儲開銷。儘管zipmap 的添加,刪除,查找都是O(n),可是因爲通常對象的field
數量都不太多。因此使用zipmap 也是很快的,也就是說添加刪除平均仍是O(1)。若是field
或者value 的大小超出必定限制後,redis 會在內部自動將zipmap 替換成正常的hash 實現.
這個限制能夠在配置文件中指定。
hash-max-zipmap-entries 64 #配置字段最多64
hash-max-zipmap-value 512 #配置value 最大爲512 字節

 

hset key field value 設置 hash field爲指定值,若是 key不存在,則建立

返回值:

若是 field 是哈希表中的一個新建域,而且值設置成功,返回 1 。

若是哈希表中域 field 已經存在且舊值已被新值覆蓋,返回 0 。

 

3.1 設置屬性

3.1.1 設置單個屬性--HSET

HSET key field value

例子:

hset py3 name '郭靖'

 

 

 

3.1.2 設置多個屬性--HMSET

HMSET key field value [field value ...]

hmset py4 name 'gj' gender '0'

 

 

3.2 獲取屬性

3.2.1 獲取一個屬性的值--HGET

HGET key field

 

 

3.2.2 獲取多個屬性的值--HMGET

HMGET key field [field ...]

 

 

3.2.3 獲取全部屬性和值--HGETALL

HGETALL key

 

 

3.2.4 獲取全部的屬性--HKEYS

HKEYS key

 

 

3.2.4 返回包含屬性的個數--HLEN

HLEN key

 

 

3.2.5 獲取全部值--HVALS

HVALS key

 

 

3.3 其它

3.3.1 判斷屬性是否存在--

HEXISTS key field

 

 

3.3.2 刪除屬性及值

HDEL key field [field ...]

 

 

4. list(後面的爬蟲用到)

1列表的元素類型爲string

2按照插入順序排序

3在列表的頭部或者尾部添加元素

 

4.1 設置

4.1.1 在頭部插入數據--LPUSH--(爬蟲用到這個語句)

語法和案例

LPUSH key value [value ...]

案例

lpush py5 'abc' 'efg'

 

 

 

查看數據

 

 

查看類型

 

 

4.1.2 在尾部插入數據--RPUSH

RPUSH key value [value ...]

具體案例

rpush py5 'hij' 'qlm' 

 

 

查看插入的數據

 

 

4.1.3 在一個元素的前|後插入新元素--linsert

LINSERT key BEFORE|AFTER pivot value

具體案例:

linsert py5 after 'abc' '123'

  • 設置指定索引的元素值
  • 索引是基於0的下標
  • 索引能夠是負數,表示偏移量是從list尾部開始計數,如-1

 

 

 

4.1.4 示列表的最後一個元素--LSET

LSET key index value

 

 

 

4.2 獲取

4.2.1 返回存儲在 key 的列表裏指定範圍內的元素

  • start end 偏移量都是基於0的下標
  • 偏移量也能夠是負數,表示偏移量是從list尾部開始計數,如-1表示列表的最後一個元素

LRANGE key start stop

例如:

lrange py5 2 -1

 

 

 

4.2.2 移除而且返回 key 對應的 list 的第一個元素

LPOP key

lpop py5

 

 

4.2.3 移除並返回存於 key 的 list 的最後一個元素

RPOP key

案例:

ppop py5

 

 

4.3 其它

4.3.1 裁剪列表,改成原集合的一個子集

  • start end 偏移量都是基於0的下標
  • 偏移量也能夠是負數,表示偏移量是從list尾部開始計數,如-1表示列表的最後一個元素

LTRIM key start stop

案例:

ltrim py5 1 2

 

 

 

4.3.2 返回存儲在 key 裏的list的長度

LLEN key

 

 

4.3.3 返回列表裏索引對應的元素

LINDEX key index

 

 

5. set

1無序集合

2元素爲string類型

3元素具備惟一性,不重複

 

5.1 設置

5.1.1 添加元素--SADD

SADD key member [member ...]

例子:

sadd py6 abc 123 defg

 

 

 

5.2 獲取

5.2.1 返回key集合全部的元素--SMEMBERS

SMEMBERS key

例子:獲得py6集合全部元素

smembers py6

 

 

5.2.2 返回集合元素個數--SCARD

SCARD key

例如:查看py6集合元素的個數

scard py6

 

 

5.3 其它

5.3.1 準備數據

sadd py6 defg 123 abc 456

sadd py7 abc 123 world 456

 

 

 

 

5.3.2 求多個集合的交集--sinter

SINTER key [key ...]

如:求py6和py7兩個集合的交集

sinter py6 py7

 

 

  • 求某集合與其它集合的差集

SDIFF key [key ...]

例如:從py6中減掉py7中py6也存在的元素

sdiff py6 py7

例如:從py7中減掉py6中py7也存在的元素

sdiff py7 py6

 

 

  • 求多個集合的合集

SUNION key [key ...]

例如:

sunion py6 py7

 

 

 

  • 判斷元素是否在集合中

SISMEMBER key member

 

 

6. zset

1sorted set,有序集合

2元素爲string類型

3元素具備惟一性,不重複

4每一個元素都會關聯一個double類型的score,表示權重,經過權重將元素從小到大排序

5元素的score能夠相同

 

6.1 設置

6.1.1 添加--ZADD

ZADD key score member [score member ...]

 

 

 

6.2 獲取

6.2.1 返回指定範圍內的元素--ZRANGE

ZRANGE key start stop

 

 

6.2.2 返回元素個數--ZCARD

ZCARD key

 

 

6.2.3 返回有序集key中,score(權重)值在min和max之間的成員--ZCOUNT

ZCOUNT key min max

 

 

6.2.4 返回有序集key中,成員member的score值--ZSCORE

ZSCORE key member

 

 

4、高級

  • 主要討論發佈訂閱模塊、主從配置兩個知識點

1. 發佈訂閱

 

 

發佈者不是計劃發送消息給特定的接收者(訂閱者),而是發佈的消息分到不一樣的頻道,不須要知道什麼樣的訂閱者訂閱。

訂閱者對一個或多個頻道感興趣,只需接收感興趣的消息,不須要知道什麼樣的發佈者發佈的。

發佈者和訂閱者的解耦合能夠帶來更大的擴展性和更加動態的網絡拓撲。

客戶端發到頻道的消息,將會被推送到全部訂閱此頻道的客戶端。

客戶端不須要主動去獲取消息,只須要訂閱頻道,這個頻道的內容就會被推送過來。

1.1 消息的格式

  • 推送消息的格式包含三部分
  • part1:消息類型,包含三種類型
    • subscribe,表示訂閱成功
    • unsubscribe,表示取消訂閱成功
    • message,表示其它終端發佈消息
  • 若是第一部分的值爲subscribe,則第二部分是頻道,第三部分是如今訂閱的頻道的數量
  • 若是第一部分的值爲unsubscribe,則第二部分是頻道,第三部分是如今訂閱的頻道的數量,若是爲0則表示當前沒有訂閱任何頻道,當在Pub/Sub之外狀態,客戶端能夠發出任何redis命令
  • 若是第一部分的值爲message,則第二部分是來源頻道的名稱,第三部分是消息的內容

1.2 命令

1.2.1 切換數據

select 0

或者

select 1

 

 

1.2.2 訂閱

說明,

SUBSCRIBE 頻道名稱 [頻道名稱 ...]

subscribe頻道名稱 [頻道名稱 ...]

 

 

 

1.2.3 在另一個終端上

 

 

1.2.4 取消訂閱

直接使用Ctrl+c退出也能夠取消訂閱

  • 若是不寫參數,表示取消全部訂閱

UNSUBSCRIBE 頻道名稱 [頻道名稱 ...]

或者

unsubscribe 頻道名稱 [頻道名稱 ...]

 

由於訂閱平道後當前終端處於阻塞狀態,沒法輸入取出訂閱命令,那麼在使用Python代碼交互的時候,使用該該命令用於取消訂閱某個或者一些頻道。

1.2.5 發佈

PUBLISH 頻道 消息

或者

publish 平道 消息

 

 

 

1.2.6 接收的兩個終端

 

 

 

 

2. 主從配置

 

一個master能夠擁有多個slave,一個slave又能夠擁有多個slave,如此下去,造成了強大的多級服務器集羣架構

好比,將ip192.168.1.10的機器做爲主服務器,將ip192.168.1.11的機器做爲從服務器

2.1. 設置主服務器的配置

使用vim或者其餘文本工具找到redis.conf配置文件

sudo vim /etc/redis/redis.conf

設置主服務器的配置

bind 192.168.1.29

 

 

保存退出,而且重啓redis服務器

 

 

2.2. 設置從服務器的配置

使用vim或者其餘文本工具找到redis.conf配置文件

sudo vim /etc/redis/redis.conf

注意:在slaveof後面寫主機ip,再寫端口,並且端口必須寫

bind 192.168.1.91

slaveof 192.168.1.29 6379

 

 

保存退出,而且重啓redis服務器

 

 

2.3. 在主服務器

masterslave分別執行info命令,查看輸出信息

2.3.1 進入客戶端

redis-cli -h 192.168.1.29

 

 

2.3.2 master上寫數據

set hello world

 

 

2.3.3 slave上讀數據

Slave機器上本身的ip,必定要指定,不然會沒有數據

get hello

 

 

 

5、Redis與Python交互

1. 安裝包

中文官網(http://redis.cn/clients.html)查找客戶端代碼

1.1 安裝方式一:聯網命令安裝

sudo pip3 install redis

 

1.2 安裝方式二:使用源碼安裝

unzip redis-py-master.zip

cd redis-py-master

sudo python setup.py install

 

2. 交互代碼

2.1 引入模塊

import redis

 

2.2 鏈接

try:
   red = redis.StrictRedis(host="192.168.31.114",port=6379)
except Exception as e:
   print(e)

 

  • 方式一:根據數據類型的不一樣,調用相應的方法,完成讀寫
  • 更多方法同前面學的命令
else:
   #name是key,hello world是值
   red.set("name","hello world")
   #根據key獲得值
   print(red.get("name"))#b'hello world'

 

 

運行效果:

 

 

  • 方式二:pipline
  • 緩衝多條命令,而後一次性執行,減小服務器-客戶端之間TCP數據庫包,從而提升效率
#緩衝多條命令,而後一次性執行,減小服務器-客戶端之間TCP數據庫包,從而提升效率
pipe = red.pipeline()
pipe.set('name', 'world')
print(pipe.get('name'))
#執行命令
pipe.execute()

 

3. 封裝

  • 鏈接redis服務器部分是一致的
  • 這裏將string類型的讀寫進行封裝

模塊test.py代碼以下:

import redis

class RedisHelper():
    def __init__(self,host='192.168.31.114',port=6379):
        self.__redis = redis.StrictRedis(host, port)
    def get(self,key):
        if self.__redis.exists(key):
            return self.__redis.get(key)
        else:
            return ""
    def set(self,key,value):
        self.__redis.set(key,value)

if __name__ == "__main__":

   red = RedisHelper()
   #name是key,hello world是值
   red.set("name","hello world")
   #根據key獲得值
   print(red.get("name"))#b'hello world'

 

6、綜合案例:用戶登陸

 

 

1. 需求說明

業務過程以下:

輸入用戶名、密碼

密碼加密

判斷redis中是否記錄了用戶名,若是有則成功

若是redis中沒有用戶名,則到mysql中查詢

mysql中查詢成功後,將用戶名記錄到redis

2. 代碼實現

2.1 封裝好的MySQL工具模塊MySQLUtils.py

import pymysql
import redis

class RedisHelp(object):
   def __init__(self,host="192.168.31.114",port=6379):
      self.__redis = redis.StrictRedis(host=host,port=port)


   def get(self,key):
      if self.__redis.exists(key):
         return self.__redis.get(key)
      else:
         return ""

   def set(self,key,value):
      self.__redis.set(key,value)


class MySQLHelp(object):
   def __init__(self,host):
      self.host=host
      self.port=3306
      self.user='afu'
      self.password='123456'
      self.db='python2'
      self.charset='utf8'


   #創建連接
   def open(self):
      self.conn = pymysql.connect(
         host=self.host,
         port=self.port,
         user=self.user,
         password=self.password,
         db=self.db,
         charset=self.charset
         )
      #執行sql語句和查詢數據
      self.cursor = self.conn.cursor()

   #關閉連接,釋放資源
   def close(self):

      self.cursor.close()
      self.conn.close()

   #獲得因此數據
   def get_all(self,sql,params=[]):
      result = None
      try:
         #打開連接
         self.open()
         self.cursor.execute(sql,params)
         #獲得數據
         result = self.cursor.fetchall()
         return result
      except Exception as e:
         print(e)
         # self.close()
      return result

   # 獲得因此數據
   def get_one(self, sql, params=[]):
      result = None
      try:
         # 打開連接
         self.open()
         self.cursor.execute(sql, params)
         # 獲得數據
         result = self.cursor.fetchone()
         self.close()
         return result
      except Exception as e:
         print(e)
      return result

   #增長,刪除,修改--提交事務
   def cul(self, sql, params=[]):
      try:
         # 打開連接
         self.open()
         count = self.cursor.execute(sql, params)
         # 提交事務
         self.conn.commit()
         self.close()
         print("執行完畢!")
         return count
      except Exception as e:
         print(e)
         return None


   #增長數據
   def insert(self,sql,params=[]):
      return self.cul(sql,params)

   #刪除
   def delete(self,sql,params=[]):
      return self.cul(sql,params)

   # 修改
   def update(self, sql, params=[]):
      return self.cul(sql, params)

 


2.2 實現用戶登陸的代碼

from hashlib import sha1


re = RedisHelp(host="localhost")

name = input("請輸入登陸帳號:")

password = input("請登陸密碼:")
#加密後的密碼
password = sha1(password.encode()).hexdigest()


uname = re.get("uname").decode("utf-8")
upwd = re.get("upwd").decode("utf-8")
print(type(uname))
print(uname == name)

if str(uname) == name:
   if str(upwd) == password:
      print("登陸成功,數據來自redis數據庫")
   else:
      print("密碼錯誤,數據來自redis數據庫")

else:

   help = MySQLHelp("localhost")
   #(id,uname,upwd)
   sql = "select * from userinfos where uname = %s"
   params = [name]
   result = help.get_one(sql,params)  # print(result)

   if result == None:
      print("帳號不存在")
   else:
      if result[1] == name and result[2] ==password:
         print("登陸成功!來自mysql")
         #保存數據到redis下次可使用
         re.set("uname",name)
         re.set("upwd",password)

      else:
         print("密碼錯誤!")

 

 

運行結果:

 

相關文章
相關標籤/搜索