简介:本资源为南京邮电大学大数据存储与管理课程实验一的完整报告文档,面向大数据、云计算方向的学生及Redis初学者,帮助读者在Ubuntu环境下完成Redis单机与集群的安装配置,并动手实现一个文章投票网站后端。压缩包内仅含1个doc文件,约933KB,内容涵盖实验目的、环境配置、详细操作步骤、关键代码与结果分析,结构完整、可直接参考。实验以Ubuntu 16.04为平台,结合PyCharm与Another Redis Desktop Manager,依次讲解依赖安装、APT源配置、配置文件修改、六节点集群搭建与cluster命令使用,并基于rediscluster库设计String与Sorted Set数据模型,实现投票、评分与文章列表展示功能。文档还记录了连接被拒等常见问题的排查思路,适合作为课程实验报告模板与Redis入门实战参考。目前已有324人学习。
1. Redis 单机与集群环境搭建:从 Ubuntu 16.04 到投票后端跑通
在 Ubuntu 16.04 上装 Redis,最容易翻车的不是安装本身,而是装完之后连不上、集群起不来、slot 被占。这套环境在高校大数据存储与管理课程里出现频率极高,实验要求也很明确:单机装好、集群搭起来、再用 Redis 写一个文章投票网站的后端。听起来三件事,实际上每一步都有独立的坑。我见过太多人卡在ECONNREFUSED或者cluster support disabled上,最后实验报告只能抄同学的截图。这篇笔记按真实操作顺序走一遍,把版本选择、配置文件改哪里、集群怎么合、客户端怎么连、报错怎么救全部拆开。适合正在做这个实验的开发者,也适合第一次在 Linux 上部署 Redis 集群、需要一份能照着敲的流程的人。
2. 单机安装与基础配置:apt 源、配置文件、远程连接
2.1 安装前的依赖准备与 apt 源配置
Ubuntu 16.04 自带的 apt 源里 Redis 版本偏旧,实验要求的是从 Redis 官方源安装。第一步先把依赖补齐,lsb-release用来获取系统代号,curl用来下载 GPG 密钥,gpg用来处理密钥格式转换。这三样缺一个后面都会报错。
# 安装基础依赖,lsb-release 用于获取 Ubuntu 代号,curl 用于下载,gpg 用于密钥处理 sudo apt install lsb-release curl gpg装完之后导入 Redis 官方 GPG 密钥。这一步的作用是让 apt 信任 Redis 官方源的包签名,不做的话apt-get update会直接报NO_PUBKEY。
# 下载 Redis 官方 GPG 密钥并转换为 apt 可识别的格式 curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg接着把 Redis 官方源写进 apt 源列表。$(lsb_release -cs)会自动替换成当前系统的代号,Ubuntu 16.04 对应的是xenial。如果你手动写死了代号,换系统就会出错,所以这里用命令动态获取。
# 将 Redis 官方 apt 源写入源列表,signed-by 指定信任的密钥文件 echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list源配好之后更新索引并安装。注意这里包名就是redis,不是redis-server,官方源里的包名和 Ubuntu 自带源不一样,写错了会提示找不到包。
# 更新 apt 索引并安装 Redis sudo apt-get update sudo apt-get install redis安装完成后 Redis 默认不会自动启动,需要手动拉起。Ubuntu 16.04 用的是 init.d 管理方式,不是 systemd,所以启动命令是/etc/init.d/redis-server start,而不是systemctl start redis。这一点在 16.04 和 18.04 以上版本之间差异很大,很多人照着新版本的教程敲systemctl发现命令不存在,就是版本没对上。
# 启动 Redis 服务(Ubuntu 16.04 使用 init.d 方式) /etc/init.d/redis-server start启动之后建议切到 root 权限操作,因为后面要改/etc/redis/redis.conf,普通用户没有写权限。sudo -i和sudo su的区别在于前者会加载 root 的环境变量,操作配置文件时更顺手。
# 切换到 root 用户,方便后续修改配置文件和操作集群目录 sudo -i2.2 redis.conf 关键参数修改与远程连接
配置文件在/etc/redis/redis.conf,用 vim 打开。这个文件很长,但实验里真正需要改的就几个地方。我一般会先搜bind定位到网络绑定那一行。
# 打开 Redis 主配置文件 vim /etc/redis/redis.conf需要关注的参数如下:
| 参数 | 默认值 | 建议值 | 作用 |
|---|---|---|---|
| bind | 127.0.0.1 | 0.0.0.0 或虚拟机 IP | 控制哪些地址可以连接 |
| protected-mode | yes | no | 关闭保护模式,允许外部连接 |
| port | 6379 | 6379 | 监听端口 |
| daemonize | no | yes | 后台运行 |
| cluster-enabled | 注释状态 | yes(集群时) | 开启集群支持 |
bind默认只监听127.0.0.1,意味着只有本机才能连。用 Another Redis Desktop Manager 从宿主机连虚拟机的时候,必须把这里改成虚拟机的 IP 或者0.0.0.0。protected-mode在开启且没有设密码的情况下会拒绝外部连接,实验环境里直接关掉最省事。
改完配置后重启 Redis 让参数生效。注意重启命令要在 root 下执行,而且要先cd ~回到 home 目录,否则某些环境下 init 脚本会因为当前目录权限问题报错。
# 回到 home 目录后重启 Redis 服务 cd ~ /etc/init.d/redis-server restart重启之后用ifconfig查看虚拟机的 IP 地址。这个 IP 就是 Another Redis Desktop Manager 连接时填的地址。很多人连不上就是因为这里填了127.0.0.1,但客户端跑在宿主机上,127.0.0.1指向的是宿主机自己而不是虚拟机。
# 查看虚拟机网络接口信息,找到 inet addr 对应的 IP ifconfig连接的时候在 Another Redis Desktop Manager 里新建连接,Host 填虚拟机的 IP,Port 填 6379。如果提示ECONNREFUSED,先检查bind和protected-mode,再确认虚拟机和宿主机之间网络互通。实验里遇到的第一个坑就是这个:网上说关掉安全模式就行,但实际改完protected-mode还是连不上,最后发现是bind没改。两个参数要一起改才有效。
提示:改完配置文件后一定要重启 Redis,直接改文件不重启是不会生效的。重启后可以用
redis-cli ping确认服务是否正常,返回PONG就说明单机没问题了。
3. 集群搭建:六节点配置、启动与 cluster create
3.1 集群目录规划与节点配置文件
单机跑通之后开始搭集群。实验要求是 3 主 3 从,共 6 个节点,端口分别是 6379、6380、6381 作为 master,6389、6390、6391 作为 slave。先在/opt/redis/cluster下建目录,日志单独放一个子目录,方便排查问题的时候翻日志。
# 创建集群配置目录和日志目录 mkdir -p /opt/redis/cluster mkdir -p /opt/redis/cluster/log cd /opt/redis/cluster把系统自带的redis.conf复制过来作为模板,然后基于它改出 6 份配置。直接改系统那份配置会影响单机环境,复制出来各节点独立配置更干净。
# 复制系统 Redis 配置作为集群节点配置的模板 cp /etc/redis/redis.conf /opt/redis/cluster/创建第一个 master 节点的配置文件redis-6379.conf。每个节点的配置核心差异在端口、数据目录、日志文件、pid 文件这几项,其余保持一致。
# 创建 6379 节点配置文件 touch redis-6379.conf vi redis-6379.confredis-6379.conf里需要写清楚的关键配置项:
# 端口,每个节点不同 port 6379 # 后台运行 daemonize yes # 数据存储目录,每个节点独立,避免数据互相覆盖 dir /var/lib/redis/6379 # 日志文件路径,按端口区分 logfile /opt/redis/cluster/log/redis_6379.log # pid 文件路径,按端口区分 pidfile /var/run/redis_6379.pid # 开启集群模式,这是集群搭建的核心开关 cluster-enabled yes # 集群配置文件,由 Redis 自动维护,不要手动改 cluster-config-file nodes-6379.conf # 节点超时时间,单位毫秒 cluster-node-timeout 15000 # 关闭保护模式,允许集群节点之间通信 protected-mode no # 绑定地址,集群模式下建议绑定具体 IP 或 0.0.0.0 bind 0.0.0.0cluster-enabled yes是集群能不能起来的决定性参数。默认配置里这一行是被注释掉的,如果不打开,后面执行cluster create会直接报ERR This instance has cluster support disabled。实验里踩的第二个坑就是这个,报错信息很直白,但如果不熟悉配置项,容易在配置文件里翻半天找不到。
按照同样的结构创建其余 5 个配置文件,只需要把端口号、目录、日志文件名、pid 文件名里的数字替换掉。6380 对应redis-6380.conf,以此类推。每个节点的dir目录要提前建好,否则启动时会因为目录不存在而失败。
# 批量创建各节点的数据目录 mkdir -p /var/lib/redis/6379 /var/lib/redis/6380 /var/lib/redis/6381 mkdir -p /var/lib/redis/6389 /var/lib/redis/6390 /var/lib/redis/63913.2 启动六个节点并合成集群
配置文件准备好之后逐个启动。用/usr/bin/redis-server指定配置文件路径启动,这样每个节点会读取各自的配置,不会互相干扰。
# 依次启动 6 个 Redis 节点,每个节点加载自己的配置文件 /usr/bin/redis-server /opt/redis/cluster/redis-6379.conf /usr/bin/redis-server /opt/redis/cluster/redis-6380.conf /usr/bin/redis-server /opt/redis/cluster/redis-6381.conf /usr/bin/redis-server /opt/redis/cluster/redis-6389.conf /usr/bin/redis-server /opt/redis/cluster/redis-6390.conf /usr/bin/redis-server /opt/redis/cluster/redis-6391.conf启动后用ps -ef | grep redis确认 6 个进程都在。如果少了某个节点,去看对应端口的日志文件,常见原因是端口被占用或者数据目录权限不对。
# 查看所有 Redis 进程,确认 6 个节点都已启动 ps -ef | grep redis确认全部启动后执行集群创建命令。--cluster-replicas 1表示每个 master 配一个 slave,6 个节点会自动分配成 3 主 3 从。命令里前三个地址会被分配为 master,后三个为 slave,但实际角色由 Redis 内部选举决定。
# 将 6 个节点合成一个集群,--cluster-replicas 1 表示每个主节点配一个从节点 /usr/bin/redis-cli --cluster create --cluster-replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6389 127.0.0.1:6390 127.0.0.1:6391执行后会列出主从分配方案,输入yes确认。如果这一步报ERR Slot xxx is already busy,说明之前搭集群的残留数据还在。解决办法是登录每个节点执行flushall和cluster reset,把旧数据和集群状态清干净再重新创建。
# 清理节点残留数据,在每个节点上分别执行 redis-cli -p 6379 flushall cluster reset exit6 个节点都要清一遍,少清一个都会导致 slot 冲突。清完之后重新执行cluster create命令即可。
集群创建成功后用cluster nodes查看节点信息,确认 3 主 3 从的角色分配和 slot 范围。再用cluster info看集群整体状态,cluster_state:ok表示集群健康。
# 连接集群查看节点信息 redis-cli cluster nodes cluster infocluster nodes的输出里,每个节点前面会标记master或slave,master 后面跟着负责的 slot 范围,比如0-5460、5461-10922、10923-16383。三个 master 平分 16384 个 slot,这是 Redis 集群的基本分片逻辑。
注意:集群模式下用
redis-cli连接时必须加-c参数,否则操作非当前节点负责的 key 会报MOVED错误。redis-cli -c -p 6379会自动跟随重定向。
4. 避坑与排查:连接失败、集群报错、slot 占用
4.1 客户端连接被拒:ECONNREFUSED
现象是 Another Redis Desktop Manager 连接时提示RedisClient On Error: Error: connect ECONNREFUSED 127.0.0.1:6379。原因有两个层面:一是客户端填的地址是127.0.0.1,但 Redis 跑在虚拟机里,这个地址指向的是客户端本机;二是 Redis 的bind配置只监听了127.0.0.1,没有监听虚拟机 IP。解决方法是把客户端里的 Host 改成虚拟机的实际 IP,同时确认redis.conf里bind改成了0.0.0.0或虚拟机 IP,protected-mode设为no,改完重启 Redis。
4.2 集群支持被禁用:cluster support disabled
现象是执行cluster create时提示(error) ERR This instance has cluster support disabled。原因是 Redis 默认配置里cluster-enabled是注释掉的,集群功能没有打开。解决方法是编辑每个节点的配置文件,找到cluster-enabled那一行,去掉前面的#,把值改成yes,然后重启所有节点。注意 6 个节点的配置文件都要改,漏掉任何一个都会导致集群创建失败。
4.3 slot 被占用:Slot xxx is already busy
现象是集群创建时报(error) ERR Slot 671 is already busy。原因是之前搭过集群或者写过数据,节点上还残留着旧的 slot 分配信息和数据。解决方法是登录每个节点,执行flushall清空数据,再执行cluster reset重置集群状态。两个命令都要在 6 个节点上执行,执行完重新跑cluster create。如果还不行,把各节点dir目录下的nodes-*.conf文件删掉再重启节点,这个文件记录着集群的元数据,删掉后会重新生成。
4.4 集群连接断开:connection is close
现象是用 Another Redis Desktop Manager 连接集群时提示stream on error: connection is close和cluster is ended。原因是客户端直接连了单个节点,但集群模式下数据分散在多个节点上,单点连接无法覆盖整个集群。解决方法是在客户端里使用 SSH 隧道加集群模式连接,或者用redis-cli -c从命令行操作。Another Redis Desktop Manager 连接集群时需要在连接设置里勾选 Cluster 模式,它会自动发现所有节点。
4.5 节点启动失败:端口占用或目录权限
现象是某个节点启动后ps里看不到进程。先看日志文件/opt/redis/cluster/log/redis_xxxx.log,常见原因有两个:端口被其他进程占用,用lsof -i:端口号排查;数据目录不存在或权限不对,确认dir配置的目录已经创建并且 Redis 进程有写权限。Ubuntu 16.04 下如果用 root 启动,目录权限一般没问题,但如果之前用普通用户启动过,可能会留下权限不一致的文件。
5. 投票后端验证:redis-py-cluster 连接与数据校验
5.1 安装客户端库并连接集群
Python 这边需要装redis-py-cluster,注意不是redis包。redis包不支持集群模式,连单机没问题,连集群会报错。实验里用的是pip install redis-py-cluster,装完之后导入的是rediscluster模块。
# 安装支持集群的 Python Redis 客户端 pip install redis-py-cluster连接集群的代码里,startup_nodes填集群中任意一个或多个节点地址即可,客户端会自动发现其余节点。decode_responses=True让返回结果直接是字符串,省去手动 decode 的步骤。
from rediscluster import RedisCluster # 集群节点列表,填任意一个可达节点即可自动发现整个集群 startup_nodes = [ {"host": "127.0.0.1", "port": "6379"}, {"host": "127.0.0.1", "port": "6380"}, ] # 创建集群连接,decode_responses=True 让返回值自动解码为字符串 rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True) # 验证连接 print(rc.ping())如果ping()返回True,说明 Python 客户端和集群之间的连接没问题。如果报RedisClusterException,检查节点地址和端口是否正确,以及集群状态是否ok。
5.2 文章投票核心逻辑与数据验证
投票后端的核心逻辑是:每发一篇文章,用incr生成文章 ID,用hset存文章信息,用zadd把文章和发布时间加入有序集合,然后给自己投一票,最后计算评分。关键代码结构如下:
import time def post(articleData, redis=rc): # article 计数器加 1,生成唯一文章 ID articleId = str(redis.incr('article')) article = 'article' + articleId # 用哈希存储文章信息,字段包括标题、内容、发布者等 for k, v in articleData.items(): redis.hset(article, k, v) # 记录发布时间,用有序集合按时间排序 post_time = time.time() redis.zadd('time', {article: post_time}) # 发布者自动投一票 print('即将为自己投初始票!', articleData['poster']) vote(article, articleData['poster'], True) # 计算初始评分 score(article, redis) return articleincr('article')保证文章 ID 全局唯一,集群环境下这个操作是原子的。hset把文章各个字段存成一个哈希,方便按字段读取。zadd('time', ...)用发布时间作为分值,后续可以按时间范围分页查询。vote函数内部用zadd和zincrby维护投票数和评分,score函数根据投票数和发布时间计算文章热度。
验证的时候在 Another Redis Desktop Manager 里连上集群,查看article键的值确认文章数量,查看article1、article2等哈希确认文章内容,查看time有序集合确认发布时间排序,查看score有序集合确认评分排序。如果客户端里能看到这些数据,并且 Python 程序输出的内容和输入一致,说明整个链路跑通了。
5.3 集群数据分布验证技巧
集群模式下数据会分散在不同节点上,用单机redis-cli连一个节点只能看到部分数据。验证的时候用redis-cli -c连接,它会自动跟随重定向,keys *能列出当前节点负责的 key,但不会列出所有节点的。想看全量数据,要么用 Another Redis Desktop Manager 的集群模式,要么在每个 master 节点上分别执行keys *再汇总。
我一般会用一个简单的方法确认数据分布:在 Python 里写入 10 篇文章,然后用redis-cli -c连接,执行cluster keyslot article1到cluster keyslot article10,看这些 key 落在哪些 slot 上,再对照cluster nodes里的 slot 分配,就能知道数据实际存在哪个节点。这个方法在排查数据丢失或者分布不均的时候特别有用。
提示:集群模式下
keys *命令只返回当前节点的 key,不要用它来判断数据是否写入成功。用cluster keyslot定位 key 所在的 slot,再找到对应的 master 节点去查,才是准确的做法。
从那以后我每次搭完 Redis 集群,都会先用cluster info确认状态,再用redis-cli -c写一个测试 key 并读出来,最后才跑业务代码。这个习惯帮我省掉了很多「以为集群好了其实没通」的返工。希望帮到你。
本文还有配套的精品资源,点击获取