nosql项目:基于 Redis 哨兵模式的鲜花预订配送系统
1 鲜花预订配送系统概述
1.1 项目背景
鲜花预订系统是一个实时处理用户订单、库存管理和配送跟踪的平台。系统需要处理大量并发订单,实时更新鲜花库存状态,并跟踪配送进度。传统关系型数据库难以应对高并发的订单处理和实时库存更新需求,因此采用Redis作为核心数据库,利用其高性能和丰富的数据结构特性,结合哨兵模式实现高可用性,确保系统稳定运行。
1.2 项目功能
实时订单处理:快速接收和处理用户鲜花预订订单
库存管理:实时更新鲜花库存状态,防止超卖
配送跟踪:记录和更新配送员位置信息
高可用保障:哨兵模式自动故障转移,避免服务中断
数据持久化:RDB快照+AOF日志确保订单和库存数据可恢复
1.3 技术选型
数据库:Redis 5.0.7(主从复制 + 哨兵模式)
容器化:Docker部署Redis和哨兵
数据持久化:RDB(定时快照) + AOF(实时日志)
数据结构:使用Hash、Sorted Set、List等多种Redis数据类型
编程语言:Python(用于示例代码和测试)
2 项目的部署
2.1 服务器配置
服务器角色 | IP地址 | 操作系统 | 用途 |
Redis主节点 | 10.1.1.11 | Centos7 | 处理读写请求,数据持久化 |
Redis从节点 | 10.1.1.142 | Centos7 | 复制主节点数据,分担读压力 |
Redis从节点 | 10.1.1.148 | Centos7 | 复制主节点数据,分担读压力 |
哨兵节点 | 三台服务器都部署 | 监控主从状态,自动故障转移 |
2.2 网络配置:
确保三台服务器之间网络互通,可以互相ping通。检查防火墙设置,确保Redis端口(6379)和哨兵端口(26379)开放。
# 开放Redis端口
sudo firewall-cmd --permanent --add-port=6379/tcp
sudo firewall-cmd --permanent --add-port=26379/tcp
sudo firewall-cmd --reload
# 验证网络连通性(主节点ping从节点)
ping 10.1.1.142 -c 3
ping 10.1.1.148 -c 3
3.docekr部署redis和哨兵
3.1 在主节点(10.1.1.11)上部署Redis主节点:
创建Redis配置文件redis-master.conf
cat > /data/redis/conf/redis-master.conf <<'EOF' port 6379 bind 0.0.0.0 protected-mode no daemonize no dir /data appendonly yes appendfilename "appendonly.aof" appendfsync everysec save 900 1 save 300 10 save 60 10000 requirepass 123456 masterauth 123456 maxmemory 2gb maxmemory-policy allkeys-lru EOF |
启动redis主节点容器:
docker run -d --name redis-master \
-p 6379:6379 \
-v /data/redis/conf:/usr/local/etc/redis \
-v /data/redis/data:/data \
redis:5.0.7 \
redis-server /usr/local/etc/redis/redis-master.conf
3.2 在从节点(10.1.1.142和10.1.1.148)上部署Redis从节点:
创建Redis配置文件redis-slave.conf
cat > /data/redis/conf/redis-slave.conf <<'EOF' port 6379 bind 0.0.0.0 protected-mode no daemonize no dir /data appendonly yes appendfilename "appendonly.aof" appendfsync everysec save 900 1 save 300 10 save 60 10000 replicaof 10.1.1.11 6379 requirepass 123456 masterauth 123456 maxmemory 2gb maxmemory-policy allkeys-lru EOF |
在10.1.1.142和10.1.1.148上分别启动Redis从节点容器:
docker run -d --name redis-slave \
-p 6379:6379 \
-v /data/redis/conf:/usr/local/etc/redis \
-v /data/redis/data:/data \
redis:5.0.7 \
redis-server /usr/local/etc/redis/redis-slave.conf
3.3 在所有节点上部署哨兵:
创建哨兵配置文件sentinel.conf
cat > /data/redis/conf/sentinel.conf <<'EOF' port 26379 bind 0.0.0.0 protected-mode no daemonize no logfile "/var/log/redis/sentinel.log" dir "/tmp" sentinel monitor mymaster 10.1.1.11 6379 2 sentinel auth-pass mymaster 123456 sentinel down-after-milliseconds mymaster 5000 sentinel failover-timeout mymaster 10000 sentinel parallel-syncs mymaster 1 EOF |
在所有三台服务器上启动哨兵容器
4. 集群验证:
4.1 检查主从复制:
在主节点
docker exec -it redis-master redis-cli -a 123456 info replication
Redis 主从复制已成功部署并正常运行,10.1.1.11是主节点,offset值相同表示主从数据完全同步,lag=1 表示复制延迟极低(理想状态)
4.2 检查哨兵的状态:
docker exec -it redis-sentinel redis-cli -p 26379 info sentinel
哨兵高可用集群已成功部署并正常运行
4.3 故障转移测试:
停止主节点容器docker stop redis-master
观察哨兵日志docker logs redis-sentinel | grep "failover"
节点验证:
docker exec -it redis-slave redis-cli -a 123456 info replication
检查新主节点的数据是否与原主节点一致(如订单、库存数据是否完整)
docker exec -it redis-slave redis-cli -a 123456 smembers "orders"
5.功能验证
连接redis数据库编写python脚本(仅显示核心代码)
import redis from redis.sentinel import Sentinel def test_flower_system(): # 连接 Redis Sentinel 并启用自动解码 sentinel = Sentinel( sentinels=[('10.1.1.11', 26379), ('10.1.1.142', 26379), ('10.1.1.148', 26379)], socket_timeout=0.1, password='123456' ) # 主节点连接(读写操作) master = sentinel.master_for( service_name='mymaster', socket_timeout=0.1, password='123456', decode_responses=True ) # 从节点连接(只读操作) slave = sentinel.slave_for( service_name='mymaster', socket_timeout=0.1, password='123456', decode_responses=True ) if __name__ == "__main__": test_flower_system() |
6.navicat连接redis
进入redis已经可以看到表格了
7.web页面
Vi app.py (此处只显示个别核心代码)
app = Flask(__name__) # 连接 Redis Sentinel sentinel = Sentinel( sentinels=[('10.1.1.11', 26379), ('10.1.1.142', 26379), ('10.1.1.148', 26379)], socket_timeout=0.1, password='123456' ) # 主节点连接(读写操作) master = sentinel.master_for( service_name='mymaster', socket_timeout=0.1, password='123456', decode_responses=True ) # 从节点连接(只读操作) slave = sentinel.slave_for( service_name='mymaster', socket_timeout=0.1, password='123456', decode_responses=True ) # 初始化数据(如果不存在) def init_data(): if not slave.exists("flower:1"): master.hset("flower:1", mapping={ "name": "红玫瑰", "price": 99, "stock": 50, "description": "鲜艳夺目,象征爱情", "image": "https://picsum.photos/id/152/300/300" }) master.zadd("hot_sales", { "flower:1": 100, "flower:2": 80, "flower:3": 120 }) master.geoadd("delivery_locations", (116.4074, 39.9042, "driver:001")) master.geoadd("delivery_locations", (116.4174, 39.9142, "driver:002")) print("数据初始化完成") if __name__ == '__main__': init_data() app.run(debug=True, host='0.0.0.0', port=5000) |
Vi /templates/index.html
退回上一级目录,运行app.py文件,python app. py
8.数据持久化验证:
8.1配置说明:
# RDB 快照配置(定时触发)
save 900 1 # 900秒内至少1次修改则触发快照
save 300 10 # 300秒内至少10次修改
save 60 10000 # 60秒内至少10000次修改
# AOF 日志配置
appendonly yes # 启用AOF
appendfilename "appendonly.aof" # AOF文件名
appendfsync everysec # 每秒同步一次(平衡性能与安全)
dir /data # 持久化文件存储目录
8.2 RDB快照测试
docker exec -it redis-master redis-cli -a 123456 save
ls /data/redis/data/dump.rdb
8.3 AOF日志测试
docker exec -it redis - master redis - cli - a 123456
# 假设要存储一个字符串set mykey myvalue
# 假设要存储一个哈希表hset myhash field1 value1
用ls /data/redis/data/appendonly.aof 查看 AOF 文件是否生成。
如果存在,查看文件内容,能看到记录的写操作指令。