当前位置: 首页 > news >正文

探索 Redis 缓存对系统性能的提升——项目启动与操作指南

探索 Redis 缓存对系统性能的提升——项目启动与操作指南

一、项目简介

Redis是一款高性能的键值存储数据库,以其出色的读写速度和丰富的数据结构著称,被广泛用作应用系统的缓存层。作为缓存,Redis通过将热点数据存储在内存中,显著降低数据库负载,提升响应速度,尤其适用于高并发场景。它支持字符串、哈希、列表等多种数据类型,可灵活应对不同业务需求,并提供了过期机制、持久化选项及集群部署能力,确保数据可靠性与扩展性。结合LRU淘汰策略,Redis能自动管理内存,避免溢出。此外,其原子操作和发布订阅功能进一步扩展了缓存之外的实时数据处理场景。无论是会话缓存、页面缓存还是数据库查询加速,Redis都能通过毫秒级访问大幅优化系统性能,是现代化架构中不可或缺的缓存解决方案。

在这个项目中,我们将探索 Redis 缓存对系统性能的提升作用。项目使用 Gin 框架搭建后端服务,结合 MySQL 数据库和 Redis 缓存,同时提供了一个前端仪表盘用于监控系统状态和进行压力测试。

项目地址:https://gitee.com/mbjdot/go_redis
博客地址:https://blog.tmdog114514.icu

二、项目启动步骤
1. 环境准备

确保你已经安装了 DockerDocker Compose。如果还未安装,可以参考 Docker 官方文档 进行安装。

2. 启动项目
  • 打开终端,进入项目目录。

请添加图片描述

  • 执行以下命令启动项目:
docker-compose up -d --build

这个命令会构建项目所需的 Docker 镜像,并在后台启动 MySQL、Redis 和应用服务。--build 选项会确保重新构建镜像,以包含最新的代码更改。

3. 验证项目启动

等待一段时间后,打开浏览器访问 http://localhost:8080,如果看到“数据库与系统监控仪表盘”页面,说明项目已经成功启动。

请添加图片描述

三、核心代码描述
// 用户信息处理函数
func getUserHandler(c *gin.Context) {id := c.Param("id")// 记录开始时间用于计算性能start := time.Now()//优先从Redis获取user, err := getUserFromCache(id)if err == nil {// 缓存命中atomic.AddUint64(&redisHits, 1)c.JSON(http.StatusOK, user)return}// 缓存未命中atomic.AddUint64(&redisMisses, 1)// 查询数据库atomic.AddUint64(&dbQueryCount, 1)user, err = getUserFromDB(id)// 计算查询耗时,记录慢查询elapsed := time.Since(start)if elapsed > 100*time.Millisecond {atomic.AddUint64(&slowQueryCount, 1)log.Printf("慢查询警告: 获取用户ID=%s 耗时: %v", id, elapsed)}if err != nil {atomic.AddUint64(&dbErrorCount, 1)if err == sql.ErrNoRows {c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})return}c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})return}// 将结果写入Redis(异步)go setUserToCache(user)c.JSON(http.StatusOK, user)
}

该函数的主要功能是处理用户信息获取请求,优先从 Redis 缓存中获取用户信息,如果缓存未命中,则从数据库中查询,并将查询结果异步写入 Redis 缓存。同时,代码还会记录缓存命中、缓存未命中、数据库查询次数、慢查询次数和数据库错误次数等指标。

// 从数据库获取用户信息
func getUserFromDB(userID string) (*User, error) {query := `SELECT id, name, email FROM users WHERE id = ?`switch rand.Intn(100) {case 0: // 1%概率触发锁等待超时time.Sleep(1500 * time.Millisecond)return nil, &mysql.MySQLError{Number: 1205, Message: "Lock wait timeout"}case 1, 2: // 2%概率触发高负载延迟time.Sleep(time.Duration(300+rand.Intn(700)) * time.Millisecond) // 300-1000msdefault: // 正常情况base := 15 + rand.Intn(25) // 15-40ms基础延迟time.Sleep(time.Duration(base) * time.Millisecond)}start := time.Now()row := db.QueryRow(query, userID)var user Usererr := row.Scan(&user.ID, &user.Name, &user.Email)// 记录数据库操作耗时elapsed := time.Since(start)if elapsed > 100*time.Millisecond {log.Printf("MySQL慢查询: 获取用户ID=%s 耗时: %v", userID, elapsed)}if err != nil {if err != sql.ErrNoRows {log.Printf("数据库查询错误: %v", err)}return nil, err}return &user, nil
}

我模拟了查新数据库所带来的高负载延迟与触发锁等待超时

四、项目操作指南
1. 系统监控

打开浏览器访问 http://localhost:8080,你会看到系统监控仪表盘。仪表盘会显示 Redis 和 MySQL 的状态、缓存命中率、数据库连接数等信息。你可以通过选择不同的刷新间隔,或者点击“刷新数据”按钮来更新页面数据。

请添加图片描述

2. 压力测试

在仪表盘的“压力测试”部分,你可以进行压力测试。输入测试的持续时间、并发数和测试端点,然后点击“开始测试”按钮,系统会开始进行压力测试。在测试过程中,你可以点击“停止测试”按钮来停止测试。测试结束后,系统会显示测试结果,包括总请求数、成功请求数、平均响应时间等指标。

请添加图片描述

我们发现30s的测试每秒请求次数达到了16212次,性能非常强悍。

我们直接修改代码

// 用户信息处理函数
func getUserHandler(c *gin.Context) {id := c.Param("id")// 记录开始时间用于计算性能start := time.Now()优先从Redis获取//user, err := getUserFromCache(id)//if err == nil {//	// 缓存命中//	atomic.AddUint64(&redisHits, 1)//	c.JSON(http.StatusOK, user)//	return//}// 缓存未命中atomic.AddUint64(&redisMisses, 1)// 查询数据库atomic.AddUint64(&dbQueryCount, 1)user, err := getUserFromDB(id)// 计算查询耗时,记录慢查询elapsed := time.Since(start)if elapsed > 100*time.Millisecond {atomic.AddUint64(&slowQueryCount, 1)log.Printf("慢查询警告: 获取用户ID=%s 耗时: %v", id, elapsed)}if err != nil {atomic.AddUint64(&dbErrorCount, 1)if err == sql.ErrNoRows {c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})return}c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})return}// 将结果写入Redis(异步)//go setUserToCache(user)c.JSON(http.StatusOK, user)
}

注释掉redis相关逻辑

重新部署,先关闭卸载容器docker-compose down -v ,重新构建docker-compose up -d --build

进入仪表盘并测试

请添加图片描述

发现30s测试只能请求27407次,性能大幅降低

五、总结

通过启动和操作这个项目,我们可以直观地看到 Redis 缓存对系统性能的提升作用。在后续的博客中,我们将深入分析项目的代码,探讨 Redis 缓存的实现原理和优化策略。

相关文章:

  • 论文导读 - 基于边缘计算、集成学习与传感器集群的便携式电子鼻系统
  • 解构编程语言的基因密码:论数据类型如何被语言系统定义与重塑
  • Kubernetes(k8s)学习笔记(三)--部署 Kubernetes Master
  • uni-app(vue3)动态获取swiper的区域高度以及通过scroll-view实现区域滚动和scroll-view的置顶功能
  • 纷析云开源财务软件:基于Spring Boot的轻量化财务中台实践
  • 2025系统架构师---论企业集成平台的技术与应用
  • 阿里qiankun微服务搭建
  • ShaderToy学习笔记 04.绘制多个3D对象
  • 第一章:User Interface Abstraction
  • C++复习补充 类型转换和RTTI
  • Vue 中局部指令(directives)的用法详解
  • 深入了解指针(6)
  • 微信小程序中基于 SSE 实现轻量级实时通讯 —— 原理、实践与对比分析
  • MySQL5.7.21查询入门
  • Java生成微信小程序码及小程序短链接
  • 文档在线协同工具ONLYOFFICE教程:如何使用宏突出显示具有特定提示文本的空文本字段
  • 基于YOLO的瓷砖缺陷检测系统设计与实现(附数据集+源码)
  • EMB量产首航!炯熠电子引领「线控底盘革命」
  • vue3使其另一台服务器上的x.html,实现x.html调用中的函数,并向其传递数据。
  • react中有哪几种数据结构?分别是干什么的?
  • 金科股份:去年营收约275亿元,今年确保所有项目“零烂尾”
  • 马上评|“AI神医宇宙”欺诈,连演员都不请了
  • 全过程人民民主研究基地揭牌,为推动我国民主政治建设贡献上海智慧
  • 上海明天起进入“升温通道”,五一假期冲刺33℃
  • 传染病防治法修订草案提请三审,拟加强医疗机构疾控能力建设
  • 俄罗斯称已收复库尔斯克州,普京发表讲话