Python搭建Redis集群

官網(wǎng):https://redis.io/

總結(jié)Ubuntu搭建流程:

# 安裝redis
sudo apt install redis-server
redis-server -v
redis-cli -v
# 安裝ruby
sudo apt-get install ruby rubygems
ruby -v
gem -v
# 安裝ruby插件
sudo gem install redis -v 3.0.6 (根據(jù)redis版本決定)

# 復(fù)制3份redis.conf,分別在3臺(tái)機(jī)器上(或者1臺(tái)機(jī)器上的不同文件夾)啟動(dòng)redis-server實(shí)例
redis-server redis-6379.conf
redis-server redis-6380.conf
redis-server redis-6381.conf
# 創(chuàng)建集群
redis-trib.rb create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381  # 如果是不同機(jī)器需要替換成各個(gè)機(jī)器的IP

1 什么是Redis

  • REmote DIctionary Server(Redis)
  • 是一個(gè)由Salvatore Sanfilippo寫的key-value存儲(chǔ)系統(tǒng)。
  • 基于內(nèi)存(也可以基于持久化)存儲(chǔ)
  • 通常被稱為數(shù)據(jù)結(jié)構(gòu)服務(wù)器,因?yàn)橹担╲alue)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等類型。

2 為什么用Redis

  • 讀寫性能高:讀的速度是110000次/s,寫的速度是81000次/s
  • 數(shù)據(jù)類型豐富:支持 Strings, Lists, Hashes, Sets 及 Ordered Sets
  • 原子性操作:所有的操作要么成功執(zhí)行要么失敗完全不執(zhí)行
  • 輕量化:整個(gè)軟件才2M,內(nèi)存占用極少
  • 單機(jī)多實(shí)例,同機(jī)器可以給多個(gè)應(yīng)用配置多個(gè)Redis數(shù)據(jù)庫(kù),因?yàn)橘Y源占用極少
  • 存儲(chǔ)在內(nèi)存中(幾乎是計(jì)算機(jī)存儲(chǔ)的最高讀寫速度),又支持備份到磁盤中
  • 相比較其他的NoSQL數(shù)據(jù)庫(kù)(非關(guān)系型數(shù)據(jù)庫(kù)):

(1)Memcached:
【優(yōu)點(diǎn)】利用多核優(yōu)勢(shì),吞吐可以達(dá)到幾十萬(wàn)QPS(日常5-6w QPS)。
【缺點(diǎn)】但只支持簡(jiǎn)單的key/value數(shù)據(jù)結(jié)構(gòu)(不像Redis可以支持豐富的數(shù)據(jù)類型),不能持久化,不能備份,重啟后數(shù)據(jù)消失,內(nèi)存采用Slab Allocation機(jī)制管理,value大小分布差異大的時(shí)候內(nèi)存利用率低。

(2)Redis:
【優(yōu)點(diǎn)】支持多種數(shù)據(jù)結(jié)構(gòu),支持持久化到磁盤來(lái)進(jìn)行數(shù)據(jù)備份或恢復(fù),支持通過(guò)master-slave機(jī)制做數(shù)據(jù)復(fù)制,單線程串行執(zhí)行所有命令,不需要考慮數(shù)據(jù)一致性。支持pub/sub消息訂閱機(jī)制。
【缺點(diǎn)】只能使用單線程,性能受限于CPU性能,單實(shí)例CPU最高只能達(dá)到5-6wQPS(日常1-2w QPS),在string類型上會(huì)消耗比較多的內(nèi)存,可以使用dict(hash表)壓縮存儲(chǔ)來(lái)降低內(nèi)存耗用

(3)MoongoDB:
【優(yōu)點(diǎn)】有更高的寫入速度,處理大規(guī)模單表可以很容易的分割表
【缺點(diǎn)】占用空間過(guò)大,沒(méi)有成熟的維護(hù)工具,不支持事務(wù)

  • 三者區(qū)別
    ① 簡(jiǎn)單存取key-value用memcached好一些,多數(shù)據(jù)類型用Redis,數(shù)據(jù)量比較大用MongoDB。
    ② memcached客戶端更成熟穩(wěn)定,Redis協(xié)議比Memcached復(fù)雜,但Redis實(shí)際測(cè)試表現(xiàn)比mencached好。
    ③ 大家習(xí)慣稱 『Redis緩存』『MongoDB數(shù)據(jù)庫(kù)』。
    ④MongoDB更多采用集群部署,Redis偏向于進(jìn)程順序?qū)懭耄翰渴鹨矁H限于主-從模式。

3 安裝、配置、啟動(dòng)、卸載

3.1 安裝

Windows安裝:https://www.runoob.com/redis/redis-install.html
Linux安裝:sudo apt install redis-server
Mac安裝:brew install redis
Docker安裝:不太推薦,因?yàn)镽edis實(shí)在是太輕量了
下載編譯安裝:目前最新穩(wěn)定版本為6.0.8

wget http://download.redis.io/releases/redis-6.0.8.tar.gz
tar xzf redis-*.tar.gz
cd redis-*

make
make test
sudo make install

# 執(zhí)行完 make 命令后,redis-6.0.8 的 src 目錄下會(huì)出現(xiàn)編譯后的 redis 服務(wù)程序 redis-server,還有用于測(cè)試的客戶端程序 redis-cli
cd src 
ls redis-server redis-cli

3.2 配置文件

只有一個(gè)redis.conf文件(經(jīng)常需要修改的配置如下)

# 綁定主機(jī)IP和PORT,端口是redis默認(rèn)的
bind 0.0.0.0
port 6379

# (推薦)守護(hù)進(jìn)程運(yùn)行方式開(kāi)啟,這樣不會(huì)進(jìn)入命令行"前臺(tái)堵塞模式"
daemonize yes

# pid文件
pidfile /var/run/redis_6379.pid
# 日志文件保存位置
logfile "/usr/local/redis/cluster/6379/redis.log"
# 數(shù)據(jù)文件
dbfilename dump.db
# 數(shù)據(jù)存儲(chǔ)目錄設(shè)置,運(yùn)行前需要手動(dòng)創(chuàng)建文件夾,否則報(bào)錯(cuò)
dir "/usr/local/redis/cluster/6379"

# 數(shù)據(jù)庫(kù)數(shù)量,默認(rèn)16個(gè)數(shù)據(jù)庫(kù)
database 16

# 是否從機(jī)
slaveof IP:PORT
#數(shù)據(jù)是否持久化
appendonly yes

# 集群配置
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000

3.3 啟動(dòng)和關(guān)閉

# 服務(wù)端啟動(dòng)與關(guān)閉
cd  redis-*/src
./redis-server

# 或者指定配置文件啟動(dòng)
./redis-server redis.conf

# 關(guān)閉,可以直接在原窗口Ctrl+C,或者另外起一個(gè)終端,用客戶端命令關(guān)閉服務(wù)端
./redis-cli shutdown
  • 檢查是否啟動(dòng):ps aux | grep redis
  • 如果要開(kāi)機(jī)啟動(dòng),在/etc/rc.local中加入啟動(dòng)redis的命令即可,但這樣還不如設(shè)置系統(tǒng)的service好管理。

客戶端啟動(dòng),并與服務(wù)端交互

# 進(jìn)入客戶端shell
cd  redis-*/src
./redis-cli

127.0.0.1:6379> ping      # 如果輸出 Output 說(shuō)明通信成功
127.0.0.1:6379> set test "It's working !"    # 如果輸出 OK 說(shuō)明寫入成功
127.0.0.1:6379> get test      # 如果輸出 "It's working !" 說(shuō)明讀取成功

# 關(guān)閉客戶端
127.0.0.1:6379> exit

如果想檢查redis是否有把數(shù)據(jù)持久化備份到磁盤,可以重啟redis然后再進(jìn)入客戶端去獲取之前存入的Key。

3.4 卸載Redis(注意先關(guān)閉redis相關(guān)服務(wù))

  • mac:brew uninstall redis
  • Linux:sudo apt-get purge --auto-remove redis-server
  • 本地編譯方式,卸載redis服務(wù),只需把/usr/local/bin/目錄下的redis相關(guān)文件刪除即可,為了卸載干凈,你還可以把解壓和編譯的redis包以及相關(guān)的配置和日志目錄也給刪除了(取決于配置的對(duì)應(yīng)目錄)。
rm /usr/local/bin/redis-*  # redis程序文件
rm -r /etc/redis/   # 配置目錄和內(nèi)容
rm /var/log/redis_*   # 日志
rm -r /var/lib/redis/  # 數(shù)據(jù)目錄和內(nèi)容
rm /etc/init.d/redis_*    # 初始化腳本
rm /var/run/redis_*    # 現(xiàn)有的Redis PID文件

4 單機(jī)模式

4.1 啟動(dòng)

redis-server

4.2 Python操作客戶端

From:https://github.com/andymccurdy/redis-py
安裝redis庫(kù):pip install redis

>>> import redis
>>> r = redis.Redis(host='localhost', port=6379, db=0)
>>> r.set('foo', 'bar')
True
>>> r.get('foo')
b'bar'

5 集群模式

5.1 主從方式啟動(dòng)

Master-Slave架構(gòu),實(shí)際上只是一種備份關(guān)系,只能從Master寫,可以分別從Master和Slave讀。


master-slave
  • Step1:主從機(jī)器上都安裝了redis-server
  • Step2:主從機(jī)器上都有配置文件redis.conf,并分別配置主機(jī)和從機(jī)。

主節(jié)點(diǎn)配置文件master-6379-redis.conf 修改

bind 0.0.0.0
port 6379
logfile "6379.log"
dbfilename "dump-6379.rdb"
daemonize yes  # 后臺(tái)運(yùn)行
rdbcompression yes # 壓縮數(shù)據(jù)
appendonly no # 不持久化

從節(jié)點(diǎn)配置文件slave-6380-redis.conf 修改(如果在同一臺(tái)機(jī)器上則要修改端口號(hào))

bind 0.0.0.0
port 6380
logfile "6380.log"
dbfilename "dump-6380.rdb"
daemonize yes
rdbcompression yes
slaveof 127.0.0.1:6379
  • Step3:分別啟動(dòng)redis-server *-redis.conf
  • Step4:測(cè)試主從模式,客戶端連接master節(jié)點(diǎn),set數(shù)據(jù),再分別連接slave節(jié)點(diǎn),get數(shù)據(jù)。詳細(xì)參考

5.2 集群方式啟動(dòng)

  • 集群架構(gòu):將數(shù)據(jù)分為16,384個(gè)槽(Slot),平均分給每臺(tái)機(jī)器,通過(guò)Redirection轉(zhuǎn)發(fā)數(shù)據(jù)給對(duì)應(yīng)的槽,使用Hash Table確定數(shù)據(jù)存在哪個(gè)槽
  • 集群分區(qū)Partition:在有些機(jī)器不可用、離線的時(shí)候,集群也可以繼續(xù)完成請(qǐng)求任務(wù)。
  • 啟動(dòng)方式
    復(fù)制3份redis.conf,修改三處地方(如果是不同機(jī)器可以不用修改端口)
# 主節(jié)點(diǎn)
port 6379
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000

每臺(tái)機(jī)器(節(jié)點(diǎn))啟動(dòng)1個(gè)實(shí)例

./redis-server ./redis-6379.conf

使用Ruby(Redis集群管理工具),通過(guò)Cluster相關(guān)命令幫用戶簡(jiǎn)化集群創(chuàng)建、檢查、槽遷移和均衡等常見(jiàn)的運(yùn)維操作,使用之前需要安裝Ruby(因?yàn)槲覀円褂胷edis-trib.rb幫助我們進(jìn)行簡(jiǎn)單集群配置比如分配槽位,但redis-trib.rb是由ruby語(yǔ)言編寫的所以需要安裝ruby環(huán)境。)

# 安裝ruby
# 方法1:Ubuntu 安裝
sudo apt-get install ruby rubygems
# Ubuntu 卸載
gem uninstall rails
sudo apt-get purge ruby
sudo apt-get remove ruby rubygems


# 方法2:源碼安裝
(官網(wǎng):http://www.ruby-lang.org/en/downloads/)最新穩(wěn)定版本是2.7.2
wget https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.2.tar.gz
tar -zxf ruby-*.tar.gz 
cd ruby-*
./configure --prefix=/usr/local/ruby
sudo make && make install
sudo vim /etc/profile # 加入環(huán)境變量
PATH=/usr/local/ruby/bin:$PATH
source /etc/profile

ruby安裝完成后:

# 可以使用Ruby安裝Redis插件
sudo gem install redis -v 3.0.6

接下來(lái)要用redis-trib.rb工具來(lái)構(gòu)建集群,如果是編譯安裝redis,這個(gè)工具就在編譯后的src目錄下,如果是apt安裝,找不到這個(gè)文件,可以通過(guò)github下載,注意redis必須是3.0.6及以后的。下載后chmod加執(zhí)行x權(quán)限。

# 使用ruby把3個(gè)實(shí)例創(chuàng)建起集群,中途日志會(huì)告知16364個(gè)槽位的分配情況,輸入yes確認(rèn)即可
./redis-trib.rb create IP1:6379  IP2:6379 IP3:6379  
# 構(gòu)建完成, 集群完整性檢查
./redis-trib.rb check 127.0.0.1:6379

5.3 Python操作客戶端

From:https://github.com/Grokzen/redis-py-cluster
安裝庫(kù):pip install redis-py-cluster
存正常的字符串

from rediscluster import StrictRedisCluster

startup_nodes = [{"host": "100.90.243.35", "port": "8400"},
                {"host": "100.90.243.36", "port": "8400"},
                {"host": "100.90.243.39", "port": "8400"}
                ]

# Note: decode_responses must be set to True when used with Python3
rc = StrictRedisCluster(startup_nodes=startup_nodes, decode_responses=True)

rc.set("foo", "bar")

print(rc.get("foo"))

存numpy的array

from rediscluster import StrictRedisCluster
from tqdm import tqdm
import numpy as np
import msgpack
import msgpack_numpy as m
m.patch()

class RedisCluster(object):
  def __init__(self):
    startup_nodes = [{"host": "100.90.243.35", "port": "8400"},
                {"host": "100.90.243.36", "port": "8400"},
                {"host": "100.90.243.39", "port": "8400"}
                ]
    self.rc = StrictRedisCluster(startup_nodes=startup_nodes)

  def set(self, task_name, itr, params):
    key = str(task_name) + str(itr)
    val = np.asarray(params)
    val = m.packb(val)
    return self.rc.set(key, val)

  def get(self, task_name, itr):
    key = str(task_name) + str(itr)
    out = self.rc.get(key)
    # print("TTTTTTTTTTTTTTTTT", type(out))
    out = m.unpackb(out)
    return out


if __name__ == '__main__':
  # numpy data
  d_data = np.array([[8.,2.],[3.,4.]])
  print('d_data', d_data.shape, type(d_data), d_data)

  rc = RedisCluster()
  success = rc.set('mytask', 10, d_data)

  d_out = rc.get('mytask', 10)

  print('d_out', d_out.shape, type(d_out), d_out)

參考

https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-18-04
https://blog.csdn.net/liqingtx/article/details/60330555

踩坑

1. 運(yùn)行Python腳本報(bào)錯(cuò)

  • 報(bào)錯(cuò)from rediscluster import StrictRedisCluster, importerror cannot import name 'strictrediscluster'
    原因是python庫(kù)版本默認(rèn)是最新的,而redis的版本可能比較老??梢越蛋姹緡L試,博主的redis版本是3.0.6,redis==2.10.6, redis-py-cluster==1.3.5

2. redis報(bào)warning
ResponseError: MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persist on disk. Commands that may modify the data set are disabled, because this instance is configured to report errors during writes if RDB snapshotting fails (stop-writes-on-bgsave-error option). Please check the Redis logs for details about the RDB error.(Redis無(wú)法向磁盤寫入RDB的報(bào)錯(cuò))
原因是appendonly no強(qiáng)制把redis快照關(guān)閉了導(dǎo)致不能持久化的問(wèn)題,解決方案:

  • 通過(guò)在配置文件中設(shè)置stop-writes-on-bgsave-error no(記得重啟redis服務(wù))即可避免這種問(wèn)題。
  • 如果不想重啟redis服務(wù),可以通過(guò)client設(shè)置
127.0.0.1:6379> config set stop-writes-on-bgsave-error no 

3. 安裝redis過(guò)程中報(bào)錯(cuò)
網(wǎng)上搜對(duì)應(yīng)策略

make MALLOC=libc
taskset -c 1 sudo make test
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容