Python搭建Redis集群

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 安装 【Python搭建Redis集群】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 启动和关闭
# 服务端启动与关闭 cdredis-*/src ./redis-server# 或者指定配置文件启动 ./redis-server redis.conf# 关闭,可以直接在原窗口Ctrl+C,或者另外起一个终端,用客户端命令关闭服务端 ./redis-cli shutdown

  • 检查是否启动:ps aux | grep redis
  • 如果要开机启动,在/etc/rc.local中加入启动redis的命令即可,但这样还不如设置系统的service好管理。
客户端启动,并与服务端交互
# 进入客户端shell cdredis-*/src ./redis-cli127.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读。

Python搭建Redis集群
文章图片
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:6379IP2: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 StrictRedisClusterstartup_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 outif __name__ == '__main__': # numpy data d_data = https://www.it610.com/article/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

    推荐阅读