1. 程式人生 > 實用技巧 >Redis2 GEO, redis持久化(rdb,aof), redis主從, redis哨兵

Redis2 GEO, redis持久化(rdb,aof), redis主從, redis哨兵

GEO

儲存經緯度,計算兩個點之間的距離,統計某個點周圍多少距離的其他點

北京:116.28,39.55

天津:117.12,39.08

可以計算天津到北京的距離,天津周圍50km的城市,外賣等

5個城市緯度

城市經度緯度簡稱
北京 116.28 39.55 beijing
天津 117.12 39.08 tianjin
石家莊 114.29 38.02 shijiazhuang
唐山 118.01 39.38 tangshan
保定 115.29 38.51 baoding
geoadd key longitude latitude member
舉例:
geoadd cities:locations 
116.28 39.55 beijing --你實際的專案,地理位置資訊從哪裡來的?前端傳過來的 -app,移動端,申請許可權,使用者允許了,直接呼叫手機提供的介面,得到經緯度---》調後臺介面傳給你--》拿到經緯度,放到redis中即可
  (網頁也是,問是否允許訪問你的位置,選是返回後端)
# 我現在是張三,我跟李四是朋友---》李四所在的位置,李四距離我多遠,我方圓5公里內,我的好友有誰 取出某個位置的座標 (把經緯度通過介面給前端, 前端自己處理。或者用post模組調網上現成介面[很多]顯示是哪裡,再給前端) geopos cities:locations beijing 計算兩個人之間的距離(算的是直線距離) geodist cities:locations beijing tianjin km 計算方圓多少公里內有誰(可以算房源,商鋪,好友) georadiusbymember cities:locations beijing
150 km type cities:locations # 檢視geo是什麼型別,返回zset,是有序集合型別

相關命令

geoadd key longitude latitude member #增加地理位置資訊
geoadd cities:locations 116.28 39.55 beijing #把北京地理資訊天津到cities:locations中
geoadd cities:locations 117.12 39.08 tianjin
geoadd cities:locations 114.29 38.02 shijiazhuang
geoadd cities:locations 
118.01 39.38 tangshan geoadd cities:locations 115.29 38.51 baoding geopos key member #獲取地理位置資訊 geopos cities:locations beijing #獲取北京地理資訊 geodist key member1 member2 [unit]#獲取兩個地理位置的距離 unit:m(米) km(千米) mi(英里) ft(尺) geodist cities:locations beijing tianjin km #北京到天津的距離,89公里 georadius key logitude latitude radiusm|km|ft|mi [withcoord] [withdist] [withhash] [COUNT count] [asc|desc] [store key][storedist key] georadiusbymember key member radiusm|km|ft|mi [withcoord] [withdist] [withhash] [COUNT count] [asc|desc] [store key][storedist key] #獲取指定位置範圍內的地理位置資訊集合 ''' withcoord:返回結果中包含經緯度 withdist:返回結果中包含距離中心節點位置 withhash:返回解僱中包含geohash COUNT count:指定返回結果的數量 asc|desc:返回結果按照距離中心店的距離做升序/降序排列 store key:將返回結果的地理位置資訊儲存到指定鍵 storedist key:將返回結果距離中心點的距離儲存到指定鍵 ''' georadiusbymember cities:locations beijing 150 km ''' 1) "beijing" 2) "tianjin" 3) "tangshan" 4) "baoding" '''

總結

3.2以後版本才有

geo本質時zset型別

可以使用zset的刪除,刪除指定member:zrem cities:locations beijing

redis持久化

#1 持久化:把記憶體中的資料,儲存到硬碟上
#2 兩種方案:
    -快照:rdb  (類似mysql中的Dump,把記憶體中所有資料存到硬碟中)
    -日誌:aof     (每加,修改一條記錄,記一條日誌。用來恢復資料,從頭走一遍即可恢復)

RDB

# 3 rdb持久化:三種方式,兩種手動,一種配置檔案(配置檔案)
    # 第一種:在redis-cli客戶端敲save---》通過rdb方案持久化到硬碟上,同步操作,會造成redis的阻塞
    #    (檔案策略:如果老的RDB存在,會替換老的)
      # 第二種:在redis-cli客戶端敲bgsave---》通過rdb方案持久化到硬碟上,非同步操作
    #    (檔案策略:跟save相同,如果老的RDB存在,會替換老的)
    # 第三種:配置檔案
    save   900        1
    save   300        10
    save   60         10000
    解釋:
    如果60s中改變了1w條資料,自動生成rdb,自動呼叫一下bgsave
    如果300s中改變了10條資料,自動生成rdb,自動呼叫一下bgsave
    如果900s中改變了1條資料,自動生成rdb,自動呼叫一下bgsave
    
    # 配置檔案中加入:
    save 900 1 #配置一條
    save 300 10 #配置一條
    save 60 10000 #配置一條
    dbfilename dump.rdb  # 設定啟動載入的rdb檔名字,這句不寫預設為dump.rdb  
    dir ./ #rdb檔案存在當前目錄
# 4 rdb方案有缺陷,可能會丟失資料(只是用快取)

刪除對應檔案,對應aof,rdb方式無法恢復

AOF

# 5 aof持久化方案
## AOF介紹:客戶端每寫入一條命令,都記錄一條日誌,放到日誌檔案中,如果出現宕機,可以將資料完全恢復

## aof的三種策略
日誌不是直接寫到硬碟上,而是先放在緩衝區,緩衝區根據一些策略,寫到硬碟上
always:redis--》寫命令重新整理的緩衝區---》每條命令fsync到硬碟---》AOF檔案    #耗費資源,每一條命令,調flash
everysec(預設值):redis——》寫命令重新整理的緩衝區---》每秒把緩衝區fsync到硬碟--》AOF檔案 #每秒刷一次(一般用這個)
no:redis——》寫命令重新整理的緩衝區---》作業系統決定,緩衝區fsync到硬碟--》AOF檔案 #類似python讀寫檔案,沒調flash,由系統決定
    
# 6 aof重寫
隨著命令的逐步寫入,併發量的變大, AOF檔案會越來越大,通過AOF重寫來解決該問題
本質就是把過期的,無用的,重複的,可以優化的命令,來優化
這樣可以減少磁碟佔用量,加速恢復速度

# 7 啟用aof就是修改一下配置檔案(重啟即可)
  appendonly yes #將該選項設定為yes,開啟
  # appendfilename "appendonly-${port}.aof" #檔案儲存的名字(指定aof檔名字)
  appendfilename "appendonly.aof" #檔案儲存的名字(指定aof檔名字)
  appendfsync everysec #採用第二種策略
  dir /bigdiskpath #存放的路徑
  no-appendfsync-on-rewrite yes #在aof重寫的時候,是否要做aof的append操作,因為aof重寫消耗效能,磁碟消耗,正常aof寫磁碟有一定的衝突,這段期間的資料,允許丟失(重寫策略,是否開啟)

## 公司裡可以aof rdb同時使用,就是耗費效能

  自動化運維繫統,自動安裝redis,修改配置檔案,
  給redis使用aof的持久化方案
  點按鈕,切換成aof----》開啟配置檔案---》把那幾行寫入---》重啟redis服務
  
  點個按鈕即可

redis主從

# 1 為了提高效能,擴充套件機器(讀寫分離,資料副本。一主一從,一主多從)
# 2 資料流向是單向的,從master到slave
# 3 兩種方式:(需要兩臺機器)(啟動兩個redis程序,分別監聽兩個埠)
-第一種:在客戶端cli裡執行命令
      -在本地起兩個redis服務(程序)6380是從,6379是主
            # 6380從庫基礎配置修改如下
            ## port 6380    # 修改埠
            ## dir "/opt/soft/redis/data1"    # 修改資料存放目錄
            ## logfile 6380.log    # 修改log檔名
            # 監測兩個redis程序起來沒   ps aux|grep redis-server
            ## grep --color=auto redis-server 這是監測的程序
    -登陸到從庫(6380庫, redis-cli -p 6380),執行 
      -slaveof 127.0.0.1 6379  # 主庫增刪該資料,從庫跟著改(在從庫寫入資料會報錯)
      
    -取消複製:slaveof no one
      
      
-第二種:配置檔案
    -在從節點(從資料庫)配置(重啟即可)
          slaveof ip port #配置從節點ip和埠
        slave-read-only yes #從節點只讀,因為可讀可寫,資料會亂
      
          slaveof 127.0.0.1 6379
        slave-read-only yes
# 4 一主多從呢?(從庫只能讀)
    只需要在多個從庫上配置即可

redis哨兵

架構說明

可以做故障判斷,故障轉移,通知客戶端(其實是一個程序),客戶端直接連線sentinel的地址

1 多個sentinel發現並確認master有問題

2 選舉觸一個sentinel作為領導

3 選取一個slave作為新的master

4 通知其餘slave成為新的master的slave

5 通知客戶端主從變化

6 等待老的master復活成為新master的slave

# 1 哨兵是為了保證redis'服務的高可用,一個master掛掉,服務依然可以用
# 2 哨兵搭建步驟
  -1 先做一主兩從
        6379是主mastre 
        6380是從slave
        6381是從slave
  -2 啟用哨兵(哨兵是一個redis程序,哨兵sentinel程序可以分別放在不同的機器上)
    ## 配置解釋:
sentinel monitor <master-name> <ip> <redis-port> <quorum>
告訴sentinel去監聽地址為ip:port的一個master,這裡的master-name可以自定義,quorum是一個數字,指明當有多少個sentinel認為一個master失效時,master才算真正失效
sentinel auth-pass <master-name> <password>
設定連線master和slave時的密碼,注意的是sentinel不能分別為master和slave設定不同的密碼,因此master和slave的密碼應該設定相同。
sentinel down-after-milliseconds <master-name> <milliseconds> 
這個配置項指定了需要多少失效時間,一個master才會被這個sentinel主觀地認為是不可用的。 單位是毫秒,預設為30秒
sentinel parallel-syncs <master-name> <numslaves> 
這個配置項指定了在發生failover主備切換時最多可以有多少個slave同時對新的master進行 同步,這個數字越小,完成failover所需的時間就越長,但是如果這個數字越大,就意味著越 多的slave因為replication而不可用。可以通過將這個值設為 1 來保證每次只有一個slave 處於不能處理命令請求的狀態。
sentinel failover-timeout <master-name> <milliseconds>
failover-timeout 可以用在以下這些方面:     
1. 同一個sentinel對同一個master兩次failover之間的間隔時間。   
2. 當一個slave從一個錯誤的master那裡同步資料開始計算時間。直到slave被糾正為向正確的master那裡同步資料時。    
3.當想要取消一個正在進行的failover所需要的時間。    
4.當進行failover時,配置所有slaves指向新的master所需的最大時間。不過,即使過了這個超時,slaves依然會被正確配置為指向master,但是就不按parallel-syncs所配置的規則來了。

    # vim sentinel_26379.conf #建立一個sentinel的配置檔案
      #26379埠--一個哨兵
    配置檔案:
    port 26379
    daemonize yes# 是否以守護程序的形式來跑
    dir data# 資料存放目錄
    protected-mode no#保護模式,寫不寫都行,現在不需要遠端連它
    bind 0.0.0.0#繫結
    logfile "redis_sentinel.log"#日誌存放路徑,在資料存放路徑下面
    sentinel monitor mymaster 127.0.0.1 6379 2#mymaster名字隨便命 主master地址埠號 2代表要有兩個sntinel覺得你掛了,你才是掛了
    sentinel down-after-milliseconds mymaster 30000#指定需要多少時間,master被這個sentinel主管地認為不可用.單位是毫秒,預設為30秒
    sentinel parallel-syncs mymaster 1#設定failover主備切換時,多少slave同事對新master進行同步,數字越小,切換時間越長.注:在備份的slave不可用,設為1保證每次只有一個slave處於不能處理命令請求狀態.預設為1
    sentinel failover-timeout mymaster 180000#同一個sentinel對同一個master兩次failover失敗之間的事件間隔,單位毫秒,用預設即可
    #26380埠--一個哨兵
       port 26380
       daemonize yes
    dir data1
    protected-mode no
    bind 0.0.0.0
    logfile "redis_sentinel.log"
    sentinel monitor mymaster 127.0.0.1 6379 2
    sentinel down-after-milliseconds mymaster 30000
    sentinel parallel-syncs mymaster 1
    sentinel failover-timeout mymaster 180000
    #26381埠--一個哨兵
    port 26381
    daemonize yes
    dir data2
    protected-mode no
    bind 0.0.0.0
    logfile "redis_sentinel.log"
    sentinel monitor mymaster 127.0.0.1 6379 2
    sentinel down-after-milliseconds mymaster 30000
    sentinel parallel-syncs mymaster 1
    sentinel failover-timeout mymaster 180000
    
    
    -redis-sentinel 配置檔案來啟動哨兵
    -啟動哨兵:
    redis-sentinel 配置檔案
    # ./src/redis-sentinel sentinel_26379.conf # 命令在src路徑下
    redis-sentinel sentinel_26379.conf
    redis-sentinel sentinel_26380.conf
    redis-sentinel sentinel_26381.conf
    # ps aux |grep redis # 檢視當前redis-sentinel程序
    
    -從客戶端登入到一個哨兵上
    redis-cli -p 26379 # 哨兵不能寫資料
    -輸入info
    最後一行看到
    master0:name=mymaster,status=ok,address=127.0.0.1:6379,slaves=2,sentinels=3
    # 顯示主資料庫地址埠,從資料庫數量,幾個哨兵
    -把主庫手動停掉
    shutdown
    
    -連到哨兵上,輸入info(主master自動變成了6381)
  master0:name=mymaster,status=ok,address=101.133.225.166:6381,slaves=4,sentinels=3#這是視訊結果,有問題
  master0:name=mymaster,status=ok,address=127.0.0.1:6381,slaves=2,sentinels=3#這是我的正常結果,6381變為主。從庫還是有2,實際有一個已經被關閉了
        
    -原來的主庫如果啟動,主庫會變為從庫,繼續執行redis服務(哨兵不能重啟redis服務,只能監控)(視訊碰到了問題:資料髒了)
    
    
# python客戶端連線(直接連了主庫,主庫掛掉,不能改程式碼吧)
import redis
from redis.sentinel import Sentinel

# 連線哨兵伺服器(主機名也可以用域名)
# 10.0.0.101:26379
sentinel = Sentinel([('10.0.0.101', 26379),
                     ('10.0.0.101', 26378),
                     ('10.0.0.101', 26377)
             ],socket_timeout=5)
print(sentinel)
# 獲取主伺服器地址
master = sentinel.discover_master('mymaster')
print(master)


# 獲取從伺服器地址
slave = sentinel.discover_slaves('mymaster')
print(slave)


# 獲取主伺服器進行寫入
# master = sentinel.master_for('mymaster', socket_timeout=0.5)
# w_ret = master.set('foo', 'bar')
#
#
# slave = sentinel.slave_for('mymaster', socket_timeout=0.5)
# r_ret = slave.get('foo')
# print(r_ret)