數據庫學習之旅——Redis

  • Redis介紹

    • 特點及優點

      1、開源的,使用C編寫,基於內存且支持持久化
      2、高性能的Key-Value的NoSQL數據庫
      3、支持數據類型豐富,字符串strings,散列hashes,列表lists,集合sets,有序集合sorted sets 等等
      4、支持多種編程語言(C C++ Python Java PHP ... )
      
    • 與其他數據庫對比

      1、MySQL : 關係型數據庫,表格,基於磁盤,慢
      2、MongoDB:鍵值對文檔型數據庫,值爲JSON文檔,基於磁盤,慢,存儲數據類型單一
      3、Redis的誕生是爲了解決什麼問題??
         解決硬盤IO帶來的性能瓶頸
      
    • 應用場景

      1、使用Redis來緩存一些經常被用到、或者需要耗費大量資源的內容,通過這些內容放到redis裏面,程序可以快速讀取這些內容
      2、一個網站,如果某個頁面經常會被訪問到,或者創建頁面時消耗的資源比較多,比如需要多次訪問數據庫、生成時間比較長等,
      我們可以使用redis將這個頁面緩存起來,減輕網站負擔,降低網站的延遲,比如說網站首頁等
      3、比如新浪微博
      # 新浪微博,基於TB級的內存數據庫
      # 內容 :存儲在MySQL數據庫
      # 關係 :存儲在redis數據庫
      # 數字 :粉絲數量,關注數量,存儲在redis數據庫
      # 消息隊列
      
    • DB-Engines 數據庫流行度排行榜2019年11月最新排名

    • redis 版本

      1、最新版本:5.0
      2、常用版本:2.4、2.6、2.8
      	3.0(里程碑)、3.2、3.4、4.0、5.0
      3、圖形界面管理工具(寫的一般)
      	RedisDesktopManager
      # 爲了解決負載問題,所以發明了redis
      
    • 誕生歷程

      # 1、歷史
      LLOOGG.com 幫助別的網站統計用戶信息,各個網站發送的瀏覽記錄都會存儲到存儲隊列,5-10000條記錄,多餘5條需要收費
      
      # 2、原理
      FIFO機制,先進先出,滿了進一條就出一條,網站越多,隊列越多,推入和彈出操作越多
      
      # 3、技術及問題
      開始使用MySQL進行硬盤讀寫,速度很慢,導致無法實時顯示,所以自己寫了一個列表結構的內存數據庫,程序性能不會受到硬盤IO的限制,加了持久化的功能
      
      # 4、redis數據庫戛然而生
      
    • redis 附加功能

      1、持久化
        將內存中數據保存到磁盤中,保證數據安全,方便進行數據備份和恢復
      2、發佈與訂閱功能
         將消息同時分發給多個客戶端,用於構建廣播系統
      3、過期鍵功能
         爲鍵設置一個過期時間,讓它在指定時間內自動刪除
         <節省內存空間>
         # 音樂播放器,日播放排名,過期自動刪除
      4、事務功能
         原子的執行多個操作
      5、主從複製
      6、Sentinel哨兵
      

  • Redis安裝

    • Ubuntu

      # 安裝
      sudo apt-get install redis-server
      # 服務端啓動
      sudo /etc/init.d/redis-server start | stop | restart | status
      # 客戶端連接
      redis-cli -h IP地址 -p 6379 -a 密碼
      redis-cli
      127.0.0.1:6379>ping
      PONG
      
    • Windows

      1、下載安裝包
         https://github.com/ServiceStack/redis-windows/blob/master/downloads/redis-64.3.0.503.zip
      2、解壓
      3、啓動服務端
         雙擊解壓後的 redis-server.exe 
      4、客戶端連接
         雙擊解壓後的 redis-cli.exe
      
      # 問題:關閉終端後服務終止
      # 解決:將Redis服務安裝到本地服務
      1、重命名 redis.windows.conf 爲 redis.conf,作爲redis服務的配置文件
      2、cmd命令行,進入到redis-server.exe所在目錄
      3、執行:redis-server --service-install redis.conf --loglevel verbose
      4、計算機-管理-服務-Redis-啓動
      
      # 卸載
      到 redis-server.exe 所在路徑執行:
      1、redis-server --service-uninstall
      2、sc delete Redis
      

  • 配置文件詳情

    • 配置文件所在路徑

      1、Ubuntu
      	/etc/redis/redis.conf
      
      2、windows 下載解壓後的redis文件夾中
      	redis.windows.conf 
      	redis.conf
      
    • 設置連接密碼

      1、requirepass 密碼(500行)
      2、重啓服務
         sudo /etc/init.d/redis-server restart
      3、客戶端連接
         redis-cli -h 127.0.0.1 -p 6379 -a 123456
         127.0.0.1:6379>ping
      
    • 允許遠程連接

      1、註釋掉本地IP地址綁定
        69行: # bind 127.0.0.1 ::1
      2、關閉保護模式(默認開啓,把yes改爲no)
        88行: protected-mode no
      3、重啓服務
        sudo /etc/init.d/redis-server restart
      
    • 遠程連接測試(Windows連接Ubuntu的Redis服務)

      # cmd命令行
      1、d:
      2、cd Redis3.0
      3、redis-cli -h x.x.x.x
      4、x.x.x.x:6379>ping
          
      # RedisDesktopManage 連接,注意windows防火牆問題(關閉)
      

  • 數據類型

    • 字符串類型(string)

      • 特點

        字符串、數字、都會轉化爲字符串來存儲

      • 基本命令

        1、set key value
        2、setnx key value
        3、set key value ex seconds
        4、get key
        5、mset key1 value1 key2 value2 
        6、mget key1 key2 key3 
        7、stren key 
        # 數字操作
        8、incr key
        9、decr key
        
      • 擴展命令

        1、append key value
        2、setrange key index value
        3、getrange key start stop
        4、incrby key step
        5、decrby key step
        
      • 常用命令

        set | get命令
        作用: 設置鍵值,獲取鍵對應的值
        命令格式:  
        				set key value
                		get key
                		
        set命令之 - setnx 
        # 鍵不存在,進行設置,如果鍵已經存在,則不進行任何操作
        setnx key value : 鍵不存在時才能進行設置(重要)
        
        set命令之 - ex
        作用: 設置過期時間
        命令格式: set key value ex seconds
        
        mset | mget
        mset key1 value1 key2 value2 key3 value3 ... ...
        mget key1 key2 key3 ... ...
        作用: 同時設置多個值,獲取多個值
        
      • 鍵命名規範

        利用層級關係
        mset  dayin:email  [email protected]  dy:email [email protected]
        
        
      • strlen命令

        作用: 獲取值的長度
        命令格式: strlen key
        
        127.0.0.1:6379> strlen name
        (integer) 11
        127.0.0.1:6379> 
        
      • 字符串索引操作

        setrange key 索引值 value
        作用: 從索引值開始,value替換原內容
        
        127.0.0.1:6379> get message
        "hello world"
        127.0.0.1:6379> setrange message 6 'dayin'
        (integer) 12
        127.0.0.1:6379> get message
        "hello dayin"
        127.0.0.1:6379> 
        
        
        getrange key 起始值 終止值
        作用: 獲取指定範圍切片內容
        127.0.0.1:6379> get message
        "hello dayin"
        127.0.0.1:6379> getrange message 0 4
        "hello"
        127.0.0.1:6379> getrange message 0 -1
        "hello dayin"
        
      • append key value

        作用: 追加拼接value的值
        
        127.0.0.1:6379> set message 'hello '
        OK
        127.0.0.1:6379> append message 'world'
        (integer) 11
        127.0.0.1:6379> get message
        "hello world"
        127.0.0.1:6379> 
        
      • 整數操作

        INCRBY key 步長
        
        DECRBY key 步長
        
        NCR key : +1操作
        DECR key : -1操作
        
        應用場景:
        微博粉絲增加或減少就可以使用
        
      • 浮點數操作

        incrbyfloat key increment
        
      • string 命令彙總

        # 字符串操作
        1、set key value
        2、setnx key value
        3、get key
        3、mset key1 value1 key2 value2 key3 value3
        4、mget key1 key2 ke
        y3
        5、set key value ex seconds
        6、strlen key 
        # 數字操作
        7、incrby key 步長
        8、decrby key 步長
        9、incr key
        10、decr key
        11、incrbyfloat key number
        # 設置過期時間的兩種方式
        # 方式一
        1、set key value ex 3
        # 方式二
        1、set key value
        2、expire key 5 # 秒
        3、pexpire key 5 # 毫秒
        # 查看存活時間
        ttl key
        # 刪除過期
        persist key
        
      • 通用命令彙總

        # 切換庫
        select number(0-15)
        # 查看所有鍵
        keys * 
        # 鍵類型
        TYPE key
        # 鍵是否存在
        exists key
        # 刪除鍵
        del key
        # 鍵重命名
        rename key newkey
        # 返回舊值並設置新值(如果鍵不存在,就創建並賦值)
        getset key value
        # 清除當前庫中所有數據(慎用)
        flushdb
        # 清除所有庫中所有數據(慎用)
        flushall
        
      • string 數據類型注意

        # key值取值原則
        1、key值不宜過長,消耗內存,且在數據中查找這類鍵值的計算成本高
        2、不宜過短,可讀性較差
        # 值
        1、一個字符串類型的值最多能存儲512M內容
        
    • 列表數據類型

      • 特點

        1、元素是字符串類型
        2、列表頭尾增刪快,中間增刪慢,增刪元素是常態
        3、元素可重複
        4、最多可包含2^32 -1個元素
        5、索引同python列表
        
      • 頭尾壓入元素(LPUSH | RPUSH)

        # LPUSH : Left
        # RPUSH : Right
        ['lucy','tom','10']
        
      • 查看|設置 列表元素

        查看(LRANGE)
        # lrange key start stop
        lrange mylist1 0 2   # 顯示前3個元素
        lrange mylist1 0 -1  # 顯示列表中所有元素
        
        獲取指定位置元素(LINDEX)
        lindex key index
        
        設置指定位置元素的值(LSET)
        lset key index value
        
        獲取列表長度(LLEN)
        llen key
        
      • 頭尾彈出元素(LPOP | RPOP)

        LPOP key : 從列表頭部彈出一個元素
        
        RPOP key : 從列表尾部彈出一個元素
        
        RPOPLPUSH source destination : 從一個列表尾部彈出元素壓入到另一個列表頭部
        rpoplpush mylist1 mylist2
        
      • 移除指定元素(LREM)

        LREM key count value
        count>0:表示從頭部開始向表尾搜索,移除與value相等的元素,數量爲count
        count<0:表示從尾部開始向表頭搜索,移除與value相等的元素,數量爲count
        count=0:移除表中所有與value相等的值
        
        示例:
        lrem mylist 0 tom
        lrem mylist 1 tom
        lrem mylist -2 tom
        
      • 去除指定範圍外元素(LTRIM)

        LTRIM key start stop
        
        應用場景: 保存微博評論最後500條
        weibo:comments   [評論,評論,。。。。。,。。。。] 
        # LPUSH (考慮列表中元素順序)
        LTRIM weibo:comments 0 499
        # RPUSH
        LRTIM weibo:comments -500 -1
        
      • 列表中插入值(LINSERT)(瞭解)

        LINSERT key BEFORE|AFTER value  new_value
        key和pivot不存在,不進行任何操作
        示例代碼
        [1 2 3 4 5 2 ]
        LINSERT mylist after 2 8
        
      • 阻塞彈出(BLPOP | BRPOP)(重要)

        BLPOP key timeout
        
        BRPOP key timeout
        
        1、如果彈出的列表不存在或者爲空,就會阻塞
        2、超時時間設置爲0,就是永久阻塞,直到有數據可以彈出
        3、如果多個客戶端阻塞再同一個列表上,使用First In First Service原則,先到先服務
        
        示例:
        brpop mylist 0 # 永久阻塞
        brpop mylist 3 # 超時時間3秒
        
      • 列表常用命令總結

        # 增
        1、LPUSH key value1 value2 
        2、RPUSH key value1 value2
        3、RPOPLPUSH source destination
        4、LINSERT key after|before value newvalue
        # 查
        5、LRANGE key start stop
        6、LLEN key
        # 刪
        7、LPOP key
        8、RPOP key
        9、BLPOP key timeout
        10、BRPOP key timeout
        11、LREM key count value
        12、LTRIM key start stop # 微博評論500條
        # 改
        13、LSET key index newvalue
        
    • 位圖操作

      • 定義

        1、位圖不是真正的數據類型,它是定義在字符串類型中
        2、一個字符串類型的值最多能存儲512M字節的內容,位上限:2^32
        # 1MB = 1024KB
        # 1KB = 1024Byte(字節)
        # 1Byte = 8bit(位)
        
      • 強勢點

        可以實時的進行統計,極其節省空間。官方在模擬1億2千8百萬用戶的模擬環境下,
        在一臺MacBookPro上,典型的統計如“日用戶數”的時間消耗小於50ms, 佔用16MB內存
        
      • 常用命令

        # 設置某一位上的值(offset是偏移量,從0開始)
        setbit key offset value
        # 獲取某一位上的值
        GETBIT key offset
        # 統計鍵所對應的值中有多少個 1 
        BITCOUNT key
        
      • 應用場景案例

        網站用戶的上線次數統計(尋找活躍用戶)
        用戶名爲key,上線的天作爲offset,上線設置爲1
        
        示例: 用戶名爲 user001 的用戶,今年第1天上線,第30天上線
        
        SETBIT user001 0 1 
        SETBIT user001 29 1
        BITCOUNT user001
        
    • Hash散列數據類型

      • 定義

        1、由field和關聯的value組成的鍵值對
        2、field和value是字符串類型
        3、一個hash中最多包含2^32-1個鍵值對
        
      • 優點

        1、節約內存空間
        2、每創建一個鍵,它都會爲這個鍵儲存一些附加的管理信息(比如這個鍵的類型,這個鍵最後一次被訪問的時間等)
        3、鍵越多,redis數據庫在儲存附件管理信息方面耗費內存越多,花在管理數據庫鍵上的CPU也會越多
        
      • 缺點(不適合hash情況)

        1、使用二進制位操作命令:SETBIT、GETBIT、BITCOUNT等,如果想使用這些操作,只能用字符串鍵
        2、使用過期鍵功能:鍵過期功能只能對鍵進行過期操作,而不能對散列的字段進行過期操作
        
      • 基本命令操作

        # 1、設置單個字段
        HSET key field value
        HSETNX key field value
        # 2、設置多個字段
        HMSET key field value field value
        # 3、返回字段field個數
        HLEN key
        # 4、判斷字段是否存在(不存在返回0)
        HEXISTS key field
        # 5、返回字段值
        HGET key field
        # 6、返回多個字段值
        HMGET key field filed
        # 7、返回所有的鍵值對
        HGETALL key
        # 8、返回所有字段名
        HKEYS key
        # 9、返回所有值
        HVALS key
        # 10、刪除指定字段
        HDEL key field field field
        # 11、在字段對應值上進行整數增量運算
        HINCRBY key field increment
        # 12、在字段對應值上進行浮點數增量運算
        HINCRBYFLOAT key field increment
        
      • 應用場景:微博好友關注

        1、用戶ID爲key,Field爲好友ID,Value爲關注時間
        	   key          field    value
            user:10000    user:606  20190520
        	              user:605  20190521
        2、用戶維度統計
           統計數包括:關注數、粉絲數、喜歡商品數、發帖數
           用戶爲key,不同維度爲field,value爲統計數
           比如關注了5人
        	HSET user:10000 fans 5
        	HINCRBY user:10000 fans 1
        
    • 集合數據類型(set)

      • 特點

        1、無序、去重
        2、元素是字符串類型
        3、最多包含2^32-1個元素
        
      • 基本命令

        # 1、增加一個或者多個元素,自動去重
        SADD key member1 member2
        # 2、查看集合中所有元素
        SMEMBERS key
        # 3、刪除一個或者多個元素,元素不存在自動忽略
        SREM key member1 member2
        # 3、隨機彈出元素(默認彈出一個)
        SPOP key [count]
        # 4、元素是否存在
        SISMEMBER key member
        # 5、隨機返回集合中指定個數的元素,默認爲1個
        SRANDOMMEMBER key [count]
        # 6、返回集合中元素的個數,不會遍歷整個集合,只是存儲在鍵當中了
        SCARD key
        # 7、把元素從源集合移動到目標集合
        SMOVE source destination member
        # 8、差集(number1 1 2 3 number2 1 2 4)
        SDIFF key1 key2 
        # 9、差集保存到另一個集合中
        SDIFFSTORE destination key1 key2
        # 10、交集
        SINTER key1 key2
        SINTERSTORE destination key1 key2
        # 11、並集
        SUNION key1 key2
        SUNIONSTORE destination key1 key2
        
      • 應用場景: 新浪微博的共同關注

        需求: 當用戶訪問另一個用戶的時候,會顯示出兩個用戶共同關注過哪些相同的用戶
        設計: 將每個用戶關注的用戶放在集合中,求交集即可
        實現:
        
        user001 = {'peiqi','qiaozhi','danni'}
        user002 = {'peiqi','qiaozhi','lingyang'}
        
        user001和user002的共同關注爲:
        # SINTERSTORE user_all user001 user002
        # SINTER user001 user002
        
    • 有序集合 sortedset

      • 特點

        1、有序、去重
        2、元素是字符串類型
        3、每個元素都關聯着一個浮點數分值(score),並按照分值從小到大的順序排列集合中的元素(分值可以相同)
        4、最多包含2^32-1元素
        
      • 示例

        • 一個保存了水果價格的有序集合

        • 一個保存了員工薪水的有序集合

      • 增加

        zadd key score member
        # 在有序集合中添加一個成員
        zadd key score member
        # 查看指定區間元素(升序)
        zrange key start stop [withscores]
        # 查看指定區間元素(降序)
        ZREVRANGE key start stop [withscores]
        # 查看指定元素的分值
        ZSCORE key member
        # 返回指定區間元素
        # offset : 跳過多少個元素
        # count : 返回幾個
        # 小括號 : 開區間  zrangebyscore salary (6000 (8000
        zrangebyscore key min max [withscores] [limit offset count]
        limit 2 3 # 顯示第 3 4 5 三個元素
        # 刪除成員
        zrem key member
        # 增加或者減少分值
        zincrby key increment member
        # 返回元素排名
        zrank key member
        # 返回元素逆序排名
        zrevrank key member
        # 刪除指定區間內的元素
        zremrangebyscore key min max
        # 返回集合中元素個數
        zcard key
        # 返回指定範圍中元素的個數
        zcount key min max
        zcount fruits 4 7 
        zcount fruits (4 7
        # 並集
        zunionstore destination numkeys key [weights 權重值] [AGGREGATE SUM|MIN|MAX]
        # zunionstore zset4 2 zset1 zset2 aggregate max
        # 交集:和並集類似,只取相同的元素
        ZINTERSTORE destination numkeys key1 key2 WEIGHTS weight AGGREGATE SUM|MIN|MAX
        
      • 應用場景1:網易雲音樂排行榜

        1、每首歌的歌名作爲元素(先不考慮重複)
        2、每首歌的播放次數作爲分值
        3、使用ZREVRANGE來獲取播放次數最多的歌曲
        
      • 應用場景2: 京東商品暢銷榜

        # 第1天
        ZADD mobile-001 5000 'huawei' 4000 'oppo' 3000 'iphone'
        # 第2天
        ZADD mobile-002 5200 'huawei' 4300 'oppo' 3230 'iphone'
        # 第3天
        ZADD mobile-003 5500 'huawei' 4660 'oppo' 3580 'iphone'
        問題:如何獲取三款手機的銷量排名?
        # 
        1、ZADD mobile-003 5500 'huawei' 4660 'oppo' 3580 'iphone'
        2、ZUNIONSTORE mobile-001:003 mobile-001 mobile-002 mobile-003 AGGREGATE MAX
        

  • 與Python交互

    • 模塊

      • Ubuntu

        sudo pip3 install redis
        
      • Windows

        python -m pip install redis
        
      • 使用流程

        import redis
        # 創建數據庫連接對象
        r = redis.Redis(host='127.0.0.1',port=6379,db=0,password='123456')
        
      • Python操作字符串類型

        import redis
        
        r = redis.Redis(host='192.168.43.49',port=6379,password='123456',db=0)
        
        r.set('mystring','python')
        # b'python'
        print(r.get('mystring'))
        # False
        print(r.setnx('mystring','socket'))
        # mset:參數爲字典
        r.mset({'mystring2':'mysql','mystring3':'mongodb'})
        # mget:結果爲一個列表
        print(r.mget('mystring','mystring2','mystring3'))
        # mystring長度:6
        print(r.strlen('mystring'))
        # 數字類型操作
        r.set('number',10)
        r.incrby('number',5)
        r.decrby('number',5)
        r.incr('number')
        r.decr('number')
        r.incrbyfloat('number',6.66)
        r.incrbyfloat('number',-6.66)
        # b'10'
        print(r.get('number'))
        
      • 案例1:網易音樂排行榜(有序集合)

        import redis
        
        r = redis.Redis(host='192.168.43.49',port=6379,password='123456',db=0)
        
        r.zadd('ranking',{'song1':1,'song2':1,'song3':1,'song4':1})
        r.zadd('ranking',{'song5':1,'song6':1,'song7':1})
        r.zadd('ranking',{'song8':1,'song9':1})
        
        r.zincrby('ranking',50,'song3')
        r.zincrby('ranking',60,'song5')
        r.zincrby('ranking',80,'song7')
        # 獲取前10名
        rlist = r.zrevrange('ranking',0,2,withscores=True)
        
        i = 1
        for r in rlist:
            print('第%d名:%s' % (i,r[0].decode()))
            i += 1
        
      • 案例2: 京東商品暢銷榜

        import redis
        
        r = redis.Redis(host='192.168.43.49',port=6379,password='123456',db=0)
        
        # 第1天
        day01_dict = {
            'huawei' : 5000,
            'oppo'   : 4000,
            'iphone' : 3000
        }
        # 第2天
        day02_dict = {
            'huawei' : 5200,
            'oppo'   : 4300,
            'iphone' : 3230
        }
        # 第3天
        day03_dict = {
            'huawei' : 5500,
            'oppo'   : 4660,
            'iphone' : 3580
        }
        r.zadd('mobile-day01',day01_dict)
        r.zadd('mobile-day02',day02_dict)
        r.zadd('mobile-day03',day03_dict)
        
        r.zunionstore('mobile-day01:03',('mobile-day01','mobile-day02','mobile-day03'),aggregate='max')
        rlist = r.zrevrange('mobile-day01:03',0,-1,withscores=True)
        
        i = 1
        for r in rlist:
            print('第{}名:{}'.format(i,r[0].decode()) )
        

end…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章