资讯详情

Redis单机与三主三从集群搭建实战:从安装配置到投票后端开发

📅 2026/10/23 5:09:43 | 华诺云谱 👁 阅读
Redis单机与三主三从集群搭建实战:从安装配置到投票后端开发
简介本资源为南京邮电大学大数据存储与管理课程实验一的完整报告文档面向大数据、云计算方向的学生及Redis初学者帮助读者在Ubuntu环境下完成Redis单机与集群的安装配置并动手实现一个文章投票网站后端。压缩包内仅含1个doc文件约933KB内容涵盖实验目的、环境配置、详细操作步骤、关键代码与结果分析结构完整、可直接参考。实验涉及Redis官方源安装、配置文件修改、六节点集群搭建、rediscluster库使用以及基于String和Sorted Set实现文章发布、投票与评分排序等核心操作并附有连接报错等常见问题的排错思路。目前已有324人学习适合需要提交实验报告或系统练习Redis集群与Python实战的读者参考借鉴。1. 从一份实验报告说起Redis 单机、集群与投票后端到底怎么落地很多人第一次接触 Redis都是从一份课程实验报告开始的。你手里这份“大数据存储与管理实验一”就是典型在 Ubuntu 16.04 上装 Redis、搭三主三从集群、再用 Python 写一个文章投票网站的后端。听起来像教学作业但它覆盖的东西一点都不玩具——单机安装、配置文件调参、集群槽位分配、客户端连接、哈希与有序集合建模全是生产环境里天天要碰的。我见过太多人装完 Redis 就停在redis-cli ping返回 PONG 那一步真到集群和业务代码就翻车。这篇笔记就按这份实验的路径走一遍把每一步为什么这么做、参数怎么改、报错怎么查讲清楚。适合刚上手 Redis 的开发者也适合想复习集群搭建细节的老手。2. 单机 Redis 安装与配置从 apt 源到远程连接2.1 为什么不用 apt 默认源而要走官方仓库Ubuntu 自带的apt install redis-server能装但版本通常偏旧而且配置文件路径和官方包有差异。实验里用的是 Redis 官方 APT 仓库好处是版本新、后续升级方便配置文件统一在/etc/redis/redis.conf。这套流程在 Ubuntu 16.04 到 22.04 上都通用只是lsb_release -cs会自动识别代号不用手动改。先装依赖再导入 GPG 密钥然后写源列表。注意gpg --dearmor那一步是把 ASCII 密钥转成二进制格式新版 apt 要求这种格式少了它后面apt update会报签名错误。# 安装基础依赖lsb-release 用来识别系统代号 sudo apt install lsb-release curl gpg # 导入 Redis 官方 GPG 密钥--dearmor 转成 apt 可识别的二进制格式 curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg # 写入 APT 源$(lsb_release -cs) 会自动替换成 xenial/focal/jammy 等代号 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 # 更新索引并安装 sudo apt-get update sudo apt-get install redis装完之后 Redis 默认不会自动启动实验里用的是/etc/init.d/redis-server start。这是 SysV 风格的启动脚本在 systemd 系统上也能用但更推荐systemctl start redis-server。启动后先redis-cli ping返回 PONG 说明单机通了。2.2 配置文件里必须改的几个参数/etc/redis/redis.conf是核心。默认配置只监听127.0.0.1外部客户端连不上。实验里用 Another Redis Desktop Manager 连接虚拟机报ECONNREFUSED根因就是绑定地址和 protected-mode。需要改的项参数默认值建议值作用bind127.0.0.10.0.0.0 或虚拟机 IP允许外部连接protected-modeyesno内网环境关闭保护模式daemonizenoyes后台运行requirepass无按需设置连接密码改完重启/etc/init.d/redis-server restart。然后用ifconfig查虚拟机 IP客户端里填这个 IP 而不是127.0.0.1。实验报告里特别提到“网上说关 protected-mode 没解决最后改 IP 才通”其实两个都要做——protected-mode 关掉是前提IP 填对是连接目标正确。提示生产环境不要关 protected-mode 裸奔至少配requirepass加防火墙白名单。实验环境图方便可以关但要知道风险在哪。2.3 用 Another Redis Desktop Manager 验证单机客户端连接时填虚拟机 IP、端口 6379如果设了密码就填密码。连上后能看到默认 16 个数据库db0-db15。实验里后续投票网站的数据就存在 db0。这一步的意义是命令行验证的是服务本身GUI 验证的是网络可达性和客户端兼容性两个都过才算单机环境真正可用。3. 三主三从集群搭建配置文件、槽位与节点握手3.1 集群模式的核心参数单机 Redis 默认关闭集群支持直接执行cluster nodes会报ERR This instance has cluster support disabled。要开集群每个节点的配置文件里必须加# 开启集群模式 cluster-enabled yes # 集群配置文件每个节点独立不能共用 cluster-config-file nodes-6379.conf # 节点超时时间毫秒 cluster-node-timeout 15000 # 开启后台运行 daemonize yes # 绑定地址 bind 0.0.0.0 # 端口每个节点不同 port 6379 # 日志文件方便排查 logfile /opt/redis/cluster/log/redis_6379.log # 数据目录每个节点独立 dir /var/lib/redis/6379实验里建了 6 个配置文件6379、6380、6381 作为主节点6389、6390、6391 作为从节点。端口规划没有强制规则但习惯上主从端口错开一段方便记忆。每个节点的cluster-config-file和dir必须不同否则启动时会互相覆盖状态。3.2 启动节点与创建集群先建目录、复制配置模板再逐个改端口和路径。启动命令用绝对路径/usr/bin/redis-server后面跟配置文件路径# 创建集群目录和日志目录 mkdir -p /opt/redis/cluster/log # 复制默认配置作为模板 cp /etc/redis/redis.conf /opt/redis/cluster/ # 启动 6 个节点 /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 # 确认 6 个进程都在 ps -ef | grep redis6 个节点都起来后用redis-cli --cluster create合成集群。--cluster-replicas 1表示每个主节点配一个从节点6 个节点正好三主三从。命令里前三个是主候选后三个是从候选Redis 会自动分配槽位/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。成功后用redis-cli -c -p 6379进入集群模式cluster nodes能看到 6 个节点和各自角色cluster info看cluster_state:ok和槽位覆盖情况。3.3 槽位冲突与集群重置实验报告里提到ERR Slot 671 is already busy这是最典型的集群搭建翻车现场。原因是之前跑过集群nodes.conf和槽位分配残留新集群创建时发现槽位被占。解决办法是登录每个节点执行# 清空当前节点所有数据 redis-cli -p 6379 flushall # 重置集群状态清除槽位分配和节点信息 redis-cli -p 6379 cluster reset6 个节点都要执行一遍然后重新--cluster create。注意flushall会清数据生产环境慎用实验环境无所谓。另外cluster reset默认是软重置如果还不行加hard参数。注意集群创建前确保每个节点的cluster-config-file指向的文件不存在或已清理否则旧状态会被加载。4. 文章投票后端哈希、有序集合与投票逻辑4.1 数据模型设计实验参考的是《Redis in Action》1.3 节的投票网站。核心数据结构两个哈希Hash存文章详情key 是article:idfield 是 title、link、poster、time、votes、score。有序集合ZSet存排序索引。time集合按发布时间排序score集合按评分排序。文章 ID 用INCR article生成保证唯一递增。发布时间用time.time()存浮点秒数ZSet 的 score 就是它这样ZRANGE time 0 -1就是按时间倒序或正序取文章。4.2 发布文章与初始投票发布文章时先INCR拿 ID拼出article:id用HSET批量写字段再用ZADD把文章加到时间索引。然后给发布者自己投一票最后算一次评分。import time import redis # 单机连接集群用 rediscluster.RedisCluster rc redis.Redis(host127.0.0.1, port6379, decode_responsesTrue) def post(articleData, redisrc): # 文章计数器加 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}) # 发布者自动投一票 vote(article, articleData[poster], True) # 计算初始评分 score(article, redis) return articledecode_responsesTrue让返回结果是字符串而不是 bytes省得每次手动 decode。hset在 redis-py 3.x 之后支持多字段写法但实验里是循环单字段写兼容性更好。4.3 投票与评分计算投票逻辑要防重复投票。常见做法是用 Set 记录每个文章的投票用户投票前SADD返回 1 表示新投票返回 0 表示已投过。投票后更新文章的 votes 字段并重新计算评分。def vote(article, user, is_posterFalse): # 用 Set 记录投票用户SADD 返回 1 表示首次投票 if rc.sadd(article :votes, user): rc.hincrby(article, votes, 1) # 发布者初始票权重更高这里简单加 1 if is_poster: rc.hincrby(article, votes, 1) score(article, rc) def score(article, redisrc): # 评分 投票数 发布时间因子简单模拟热度衰减 votes int(redis.hget(article, votes) or 0) post_time float(redis.hget(article, time) or 0) # 时间越新加分越多这里用当前时间减发布时间 current time.time() hot votes max(0, (current - post_time) / 1000) redis.hset(article, score, hot) # 同步到评分有序集合 redis.zadd(score, {article: hot})score函数里用发布时间差做热度因子是简化版。真实场景会用votes / (time 常数)做衰减实验里不要求那么精确。关键是理解 ZSet 的 score 可以动态更新ZADD对已存在成员会覆盖分数。4.4 分组与排序查询实验里还做了文章分组用 Set 存分组关系SADD group:name article:id。查询某分组文章时先SMEMBERS拿文章列表再逐个HGETALL取详情。按评分排序则直接ZREVRANGE score 0 -1拿到文章 key 后再取哈希。# 把文章加入分组 rc.sadd(group:tech, article1) rc.sadd(group:tech, article2) # 取分组内文章 articles rc.smembers(group:tech) # 按评分降序取前 10 篇 top_articles rc.zrevrange(score, 0, 9) for a in top_articles: print(rc.hgetall(a))集群模式下smembers和zrevrange跨槽位会报 CROSSSLOT 错误需要用 hash tag 把相关 key 绑到同一槽比如group:{tech}和article:{tech}:1。实验里是单机或简单集群没踩到这个坑但生产环境必须注意。5. 避坑与排查连接、集群、客户端那些坑5.1 客户端连不上ECONNREFUSED现象Another Redis Desktop Manager 报connect ECONNREFUSED 127.0.0.1:6379。原因客户端填的是本地回环地址但 Redis 跑在虚拟机里回环地址指向客户端本机。另外bind和protected-mode没改也会拒绝外部连接。解决ifconfig查虚拟机 IP客户端填这个 IP配置文件里bind 0.0.0.0、protected-mode no重启 Redis。两步都做缺一不可。5.2 集群支持被禁用现象cluster nodes报ERR This instance has cluster support disabled。原因Redis 默认cluster-enabled no单机模式不支持集群命令。解决每个节点的配置文件里把cluster-enabled改成yes去掉行首#重启节点。注意是每个节点都要改漏一个就组不成集群。5.3 槽位已被占用现象--cluster create时报ERR Slot 671 is already busy。原因旧集群的nodes.conf和槽位分配残留新集群创建时冲突。解决每个节点执行flushall和cluster reset删掉旧的nodes-*.conf文件再重新创建集群。顺序是先重置所有节点再执行 create。5.4 集群客户端连接断开现象Another Redis Desktop Manager 连集群报stream on error: connection is close或cluster is ended。原因普通单机连接方式不支持集群的 MOVED/ASK 重定向客户端需要集群模式。解决客户端里选集群连接类型或者用 SSH 隧道加集群模式。Python 端用redis-py-cluster的RedisCluster类它会自动处理重定向。5.5 Python 客户端选型混淆现象用redis.Redis连集群部分 key 读写报 MOVED 错误。原因redis.Redis是单机客户端不处理集群重定向。解决集群用rediscluster.RedisCluster(startup_nodes[...])单机用redis.Redis。实验里pip install redis-py-cluster就是为集群准备的但投票代码如果跑在单机上用redis.Redis更简单。6. 进阶技巧用 pipeline 和 Lua 脚本把投票做稳实验里的投票逻辑是多次独立命令网络往返多并发下还可能超卖。我一般会做两件事批量操作用 pipeline 打包原子逻辑用 Lua 脚本。pipeline 把多个命令一次发出去减少 RTT# 用 pipeline 批量写文章和索引 pipe rc.pipeline() pipe.hset(article:1, mapping{title: Redis实战, poster: A}) pipe.zadd(time, {article:1: time.time()}) pipe.execute()Lua 脚本保证投票的“检查写入”原子性避免并发重复投票-- vote.lua原子投票返回 1 表示成功0 表示已投过 local voted redis.call(SADD, KEYS[1], ARGV[1]) if voted 1 then redis.call(HINCRBY, KEYS[2], votes, 1) return 1 else return 0 endPython 里用rc.eval或register_script调用。集群模式下 Lua 脚本涉及的所有 key 必须在同一槽所以 key 命名要用 hash tag比如{article1}:votes和{article1}:detail。验证集群是否健康我习惯跑一遍# 查看集群状态 redis-cli -c -p 6379 cluster info | grep cluster_state # 查看槽位覆盖 redis-cli -c -p 6379 cluster slots # 模拟故障转移停掉一个主节点看从节点是否升主 redis-cli -p 6379 shutdown sleep 5 redis-cli -c -p 6389 cluster nodes最后这条shutdown会真的停掉节点实验环境可以玩生产别乱来。从那以后我每次搭完集群都强制走一遍“停主看从”的验证确认故障转移真的生效而不是只看cluster_state:ok就放心。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑