Python搭建Redis集群

官网:https://redis.io/

总结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 (根据redis版本决定)

# 复制3份redis.conf,分别在3台机器上(或者1台机器上的不同文件夹)启动redis-server实例
redis-server redis-6379.conf
redis-server redis-6380.conf
redis-server redis-6381.conf
# 创建集群
redis-trib.rb create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381  # 如果是不同机器需要替换成各个机器的IP

1 什么是Redis

  • REmote DIctionary Server(Redis)
  • 是一个由Salvatore Sanfilippo写的key-value存储系统。
  • 基于内存(也可以基于持久化)存储
  • 通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Hash), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型。

2 为什么用Redis

  • 读写性能高:读的速度是110000次/s,写的速度是81000次/s
  • 数据类型丰富:支持 Strings, Lists, Hashes, Sets 及 Ordered Sets
  • 原子性操作:所有的操作要么成功执行要么失败完全不执行
  • 轻量化:整个软件才2M,内存占用极少
  • 单机多实例,同机器可以给多个应用配置多个Redis数据库,因为资源占用极少
  • 存储在内存中(几乎是计算机存储的最高读写速度),又支持备份到磁盘中
  • 相比较其他的NoSQL数据库(非关系型数据库):

(1)Memcached:
【优点】利用多核优势,吞吐可以达到几十万QPS(日常5-6w QPS)。
【缺点】但只支持简单的key/value数据结构(不像Redis可以支持丰富的数据类型),不能持久化,不能备份,重启后数据消失,内存采用Slab Allocation机制管理,value大小分布差异大的时候内存利用率低。

(2)Redis:
【优点】支持多种数据结构,支持持久化到磁盘来进行数据备份或恢复,支持通过master-slave机制做数据复制,单线程串行执行所有命令,不需要考虑数据一致性。支持pub/sub消息订阅机制。
【缺点】只能使用单线程,性能受限于CPU性能,单实例CPU最高只能达到5-6wQPS(日常1-2w QPS),在string类型上会消耗比较多的内存,可以使用dict(hash表)压缩存储来降低内存耗用

(3)MoongoDB:
【优点】有更高的写入速度,处理大规模单表可以很容易的分割表
【缺点】占用空间过大,没有成熟的维护工具,不支持事务

  • 三者区别
    ① 简单存取key-value用memcached好一些,多数据类型用Redis,数据量比较大用MongoDB。
    ② memcached客户端更成熟稳定,Redis协议比Memcached复杂,但Redis实际测试表现比mencached好。
    ③ 大家习惯称 『Redis缓存』『MongoDB数据库』。
    ④MongoDB更多采用集群部署,Redis偏向于进程顺序写入,集群部署也仅限于主-从模式。

3 安装、配置、启动、卸载

3.1 安装

Windows安装:https://www.runoob.com/redis/redis-install.html
Linux安装:sudo apt install redis-server
Mac安装:brew install redis
Docker安装:不太推荐,因为Redis实在是太轻量了
下载编译安装:目前最新稳定版本为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

# 执行完 make 命令后,redis-6.0.8 的 src 目录下会出现编译后的 redis 服务程序 redis-server,还有用于测试的客户端程序 redis-cli
cd src 
ls redis-server redis-cli

3.2 配置文件

只有一个redis.conf文件(经常需要修改的配置如下)

# 绑定主机IP和PORT,端口是redis默认的
bind 0.0.0.0
port 6379

# (推荐)守护进程运行方式开启,这样不会进入命令行"前台堵塞模式"
daemonize yes

# pid文件
pidfile /var/run/redis_6379.pid
# 日志文件保存位置
logfile "/usr/local/redis/cluster/6379/redis.log"
# 数据文件
dbfilename dump.db
# 数据存储目录设置,运行前需要手动创建文件夹,否则报错
dir "/usr/local/redis/cluster/6379"

# 数据库数量,默认16个数据库
database 16

# 是否从机
slaveof IP:PORT
#数据是否持久化
appendonly yes

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

3.3 启动和关闭

# 服务端启动与关闭
cd  redis-*/src
./redis-server

# 或者指定配置文件启动
./redis-server redis.conf

# 关闭,可以直接在原窗口Ctrl+C,或者另外起一个终端,用客户端命令关闭服务端
./redis-cli shutdown
  • 检查是否启动:ps aux | grep redis
  • 如果要开机启动,在/etc/rc.local中加入启动redis的命令即可,但这样还不如设置系统的service好管理。

客户端启动,并与服务端交互

# 进入客户端shell
cd  redis-*/src
./redis-cli

127.0.0.1:6379> ping      # 如果输出 Output 说明通信成功
127.0.0.1:6379> set test "It's working !"    # 如果输出 OK 说明写入成功
127.0.0.1:6379> get test      # 如果输出 "It's working !" 说明读取成功

# 关闭客户端
127.0.0.1:6379> exit

如果想检查redis是否有把数据持久化备份到磁盘,可以重启redis然后再进入客户端去获取之前存入的Key。

3.4 卸载Redis(注意先关闭redis相关服务)

  • mac:brew uninstall redis
  • Linux:sudo apt-get purge --auto-remove redis-server
  • 本地编译方式,卸载redis服务,只需把/usr/local/bin/目录下的redis相关文件删除即可,为了卸载干净,你还可以把解压和编译的redis包以及相关的配置和日志目录也给删除了(取决于配置的对应目录)。
rm /usr/local/bin/redis-*  # redis程序文件
rm -r /etc/redis/   # 配置目录和内容
rm /var/log/redis_*   # 日志
rm -r /var/lib/redis/  # 数据目录和内容
rm /etc/init.d/redis_*    # 初始化脚本
rm /var/run/redis_*    # 现有的Redis PID文件

4 单机模式

4.1 启动

redis-server

4.2 Python操作客户端

From:https://github.com/andymccurdy/redis-py
安装redis库: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 主从方式启动

Master-Slave架构,实际上只是一种备份关系,只能从Master写,可以分别从Master和Slave读。


master-slave
  • Step1:主从机器上都安装了redis-server
  • Step2:主从机器上都有配置文件redis.conf,并分别配置主机和从机。

主节点配置文件master-6379-redis.conf 修改

bind 0.0.0.0
port 6379
logfile "6379.log"
dbfilename "dump-6379.rdb"
daemonize yes  # 后台运行
rdbcompression yes # 压缩数据
appendonly no # 不持久化

从节点配置文件slave-6380-redis.conf 修改(如果在同一台机器上则要修改端口号)

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:分别启动redis-server *-redis.conf
  • Step4:测试主从模式,客户端连接master节点,set数据,再分别连接slave节点,get数据。详细参考

5.2 集群方式启动

  • 集群架构:将数据分为16,384个槽(Slot),平均分给每台机器,通过Redirection转发数据给对应的槽,使用Hash Table确定数据存在哪个槽
  • 集群分区Partition:在有些机器不可用、离线的时候,集群也可以继续完成请求任务。
  • 启动方式
    复制3份redis.conf,修改三处地方(如果是不同机器可以不用修改端口)
# 主节点
port 6379
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000

每台机器(节点)启动1个实例

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

使用Ruby(Redis集群管理工具),通过Cluster相关命令帮用户简化集群创建、检查、槽迁移和均衡等常见的运维操作,使用之前需要安装Ruby(因为我们要使用redis-trib.rb帮助我们进行简单集群配置比如分配槽位,但redis-trib.rb是由ruby语言编写的所以需要安装ruby环境。)

# 安装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:源码安装
(官网:http://www.ruby-lang.org/en/downloads/)最新稳定版本是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 # 加入环境变量
PATH=/usr/local/ruby/bin:$PATH
source /etc/profile

ruby安装完成后:

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

接下来要用redis-trib.rb工具来构建集群,如果是编译安装redis,这个工具就在编译后的src目录下,如果是apt安装,找不到这个文件,可以通过github下载,注意redis必须是3.0.6及以后的。下载后chmod加执行x权限。

# 使用ruby把3个实例创建起集群,中途日志会告知16364个槽位的分配情况,输入yes确认即可
./redis-trib.rb create IP1:6379  IP2:6379 IP3:6379  
# 构建完成, 集群完整性检查
./redis-trib.rb check 127.0.0.1:6379

5.3 Python操作客户端

From:https://github.com/Grokzen/redis-py-cluster
安装库: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. 运行Python脚本报错

  • 报错from rediscluster import StrictRedisCluster, importerror cannot import name 'strictrediscluster'
    原因是python库版本默认是最新的,而redis的版本可能比较老。可以降版本尝试,博主的redis版本是3.0.6,redis==2.10.6, redis-py-cluster==1.3.5

2. redis报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无法向磁盘写入RDB的报错)
原因是appendonly no强制把redis快照关闭了导致不能持久化的问题,解决方案:

  • 通过在配置文件中设置stop-writes-on-bgsave-error no(记得重启redis服务)即可避免这种问题。
  • 如果不想重启redis服务,可以通过client设置
127.0.0.1:6379> config set stop-writes-on-bgsave-error no 

3. 安装redis过程中报错
网上搜对应策略

make MALLOC=libc
taskset -c 1 sudo make test
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350