小白眼中的Redis。。。
mhr18 2024-12-14 11:10 16 浏览 0 评论
是一个程序员,你维护了一个 商品服务,它背后直连 mysql 数据库。假设商品服务需要对外提供 每秒 1w 次查询,但背后的 mysql 却只能提供每秒 5k 次查询,那 mysql 根本顶不住!分分钟会被压垮。
这类大流量查询场景非常常见,比如双十一秒杀和春节抢车票。那么问题就来了,有没有办法在 mysql 不被压垮的同时,让商品服务支持每秒 1w 次查询 ?当然有,没有什么是加一层中间层不能解决的,如果有,那就再加一层。这次我们要加的中间层是Redis。
本地缓存
我们知道,查询内存的速度比查询磁盘要快, mysql 数据主要存放在磁盘里,如果能将 mysql 里的数据放内存里,查询完全不走磁盘,那必然能大大提升查询性能。
我们很容易想到,可以在商品服务的内存中,申请一个字典,在 python 里叫 dict,在 java 里叫 map。
key 是商品 ID,value 是商品数据。通过商品 ID, 就能查到商品数据。
发生查询时,优先去查内存字典,没结果再跑到 mysql 数据库里查询,再将结果顺手放内存字典里,下次就又能从内存里查出来啦。
像这样,放在服务内部的缓存,就是所谓的本地缓存。有了本地缓存的加持,真正打到 mysql 的查询量就跟你喜欢的女生回你的消息字数一样少,将查询请求干到 1w qps 是很轻松的事情。
这或许是一个对你有用的开源项目,mall项目是一套基于 SpringBoot3 + Vue 的电商系统(Github标星60K),后端支持多模块和 2024最新微服务架构 ,采用Docker和K8S部署。包括前台商城项目和后台管理系统,能支持完整的订单流程!涵盖商品、订单、购物车、权限、优惠券、会员、支付等功能!
Boot项目:https://github.com/macrozheng/mall
Cloud项目:https://github.com/macrozheng/mall-swarm
视频教程:https://www.macrozheng.com/video/
项目演示:
远程缓存
但问题又来了,为了保证系统高可用,商品服务经常不止一个实例,如果每个实例都重复缓存一份本地内存,那就有些浪费内存条了。所以更好的解决方案是将这部分字典内存抽出来,单独做成一个服务。它就是所谓的远程缓存服务。
但这就引入另外一个问题,多个商品服务通过网络去读写同一份远程缓存,会存在并发问题。怎么办呢?很简单!对外不管有多少有个网络连接,收到读写命令后,都统一塞到一个线程上,在一个线程上对字典进行读写,什么并发问题和线程切换开销,完全不存在!
这个远程缓存服务足以满足大部分场景,但它属实过于简陋,我们来看下怎么优化它。
多种数据类型支持
现在缓存服务里,只有一个字典类型。key 和 value 都是字符串。但我们平时写代码的时候,还会用到很多其他内存里的数据结构,是不是也可以在缓存服务里提供类似的数据结构?于是我们对字段的 value 进行扩展,除了 字符串, 还支持先进先出的队列 List 和用于去重的 Set 类型,再加入可以做排行榜的 ZSet,现在缓存服务就更强了。
内存过期策略
缓存服务支持的数据结构变多了之后,塞到内存里的数据就越来越多了,内存又小又贵,迟早扛不住。怎么办呢?我们可以给缓存里的数据加个过期时间,一旦数据过期,就从内存里删掉,可以很大程度缓解掉内存增长速度。但问题又又来了,我怎么知道哪些数据该设置多长过期时间呢?完全没办法,只能交给调用方去做判断,让用户通过 expire 命令的形式来指定哪些数据多久过期。
缓存淘汰
但你不能指望每个调用方都是老实人,如果都不设置过期时间,那内存还是得炸。有解法吗?有!在内存接近上限的时候,根据一些策略删除掉一些内存。比如可以将最近最少使用的内存删掉,也就是所谓的 LRU,这样不仅解决了内存过大的问题,还让 redis 里的数据全是热点数据。真是一箭双雕。
持久化
现在内存过大的问题是解决了。但还有个问题,mysql 之所以过得那么舒服,那是因为前面有个缓存服务挡住了大部分流量。一旦缓存服务重启,那内存就全丢了,这时候流量会全都打到 mysql 身上,疼得它嗷嗷叫。
所以我们还需要给 redis 加入最大程度的持久化保证。确保服务重启后不至于什么数据都没有。于是可以在缓存服务里加个异步线程,定期将全量内存数据定期持久化到磁盘文件里,而这种将内存数据生成快照保存到文件的方式,就是所谓的 RDB,Redis Database Backup。
它可以每隔几分钟记录下缓存服务 的全量数据,类似于游戏的"存档"。这样就算进程挂了,重启的时候,通过加载快照文件,就能复原大部分数据。之所以说是大部分,是因为"存档"之后写入的数据可能会丢。那还有其他方式可以保留更多数据吗?有!全量数据备份当然耗时,那我们化整为零,在每次写入数据时,顺手将数据记录到文件缓存中,并每秒将文件缓存刷入磁盘,这种持久化机制叫 AOF,Append Only File,服务启动时跟着文件重新执行一遍就能将大部分数据还原,最大程度保证了数据持久化。
那问题就来了,AOF 文件会不会很大?没事,定期重写压缩就行,比如 a 被依次赋值 a=1,a=2,最终保留 a=2 就够了。
简化网络协议
刚刚提到远程缓存服务对外提供读写能力,那是对外提供的 HTTP 接口吗?当然不是!我们知道, HTTP 是基于 TCP 做的通信,实现了很多笨重的特性。既然当初是为了性能,特地上的缓存服务,那就索性彻底点,抛弃 HTTP,直接基于 TCP 做传输就好!传输协议也设计得简单点,比如只要通过 TCP 传入 SET key value,就能完成写入。传入"GET key" 就能获得对应的 value。非常简洁。那传输协议的解析需要我们自己写代码去实现吗?完全不需要,redis 官方提供了一个命令行工具,redis-cli,通过它,我们可以输入一些命令,读写 Redis 服务器里的各种内存数据。
不想用命令行也没关系,各路大神已经用各种语言将 redis-cli 支持的命令实现了一遍,完全不需要自己手写。
Redis 是什么?
好了,到这里,当初那个简陋的远程缓存服务,就成了一个高性能,支持多种数据类型和各种缓存淘汰策略,并提供一定持久化能力的超强缓存服务,没错,它就是我们常说的 Redis,全称 Remote Dictionary Server,这名字就很精辟了,说白了 redis 就是个远程的字典服务。
redis 作为架构中最常用的提速神器,是万金油一般的存在,将它放在 mysql 面前挡一道查询只是最基础的用法。通过扩展插件,还能实现各种高阶玩法。比如 RedisJSON 支持复杂的 JSON 查询和更新,说白了就是内存版本的 MongoDB。RediSearch 支持全文搜索,说白了就是内存丐版的 es。RedisGraph 支持图数据库功能,类似 Neo4j,RedisTimeSeries 处理时间序列数据,也就是内存版 InfluxDB。大有一种要在内存里将所有中间件都实现一遍的味道。
现在大家通了吗?
总结
- redis 本质上就是个远程字典服务,所有读写命令等核心逻辑,都在一个线程上完成。什么并发问题和线程切换开销,完全不存在!
- redis 支持多种数据类型、内存过期策略和多种缓存失效策略,通过 TCP 对外提供了一套非常简单的传输协议。
- redis 加入了最大程度的持久化保证。将数据持久化为 rdb 和 AOF,确保服务重启后不至于什么数据都没有。
- redis 支持多种扩展,玩法非常多,比如 RediSearch 和 RedisJSON。
相关推荐
- MYSQL数据同步(mysql数据同步方式)
-
java开发工程师在实际的开发经常会需要实现两台不同机器上的MySQL数据库的数据同步,要解决这个问题不难,无非就是mysql数据库的数据同步问题。但要看你是一次性的数据同步需求,还是定时数据同步,亦...
- SpringBoot+Redis实现点赞收藏功能+定时同步数据库
-
由于点赞收藏都是高频率的操作,如果因此频繁地写入数据库会造成数据库压力比较大,因此采用redis来统计点赞收藏浏览量,之后定时一次性写入数据库中,缓解数据库地压力。一.大体思路设计redis中的储存结...
- 双11订单洪峰:Codis代理层如何扛住Redis集群搞不定的120万QPS?
-
双11订单洪峰下的技术挑战每年的双11购物节,都是对电商平台技术架构的极限考验。当零点钟声敲响,海量用户瞬间涌入,订单量呈指数级增长,系统需要承受每秒数十万甚至上百万次的请求。作为电商系统的核心组件之...
- 基于spring boot + MybatisPlus 商城管理系统的Java开源商城系统
-
前言Mall4j项目致力于为中小企业打造一个完整、易于维护的开源的电商系统,采用现阶段流行技术实现。后台管理系统包含商品管理、订单管理、运费模板、规格管理、会员管理、运营管理、内容管理、统计报表、权限...
- 商品券后价产品设计方案(显示券后价)
-
如何设计一套高效、准确且稳定的券后价计算系统,是电商产品设计中的关键挑战之一。本文详细介绍了商品券后价的产品设计方案,从背景目标、功能设计、系统实现逻辑到异常处理机制等多个方面进行了全面阐述。一、背景...
- 外观(门面)模式-Java实现(java 门面模式)
-
定义外观模式(FacadePattern),也叫门面模式,原始定义是:为了子系统中的一组接口提供统一的接口。定义一个更高级别的接口,使子系统更易于使用。大大降低应用程序的复杂度,提高了程序的可维护性...
- Mall - 用 SpringBoot 实现一个电商系统
-
目前最为主流的Web开发技术,包括SpringBoot、MyBatis、MongoDB、Kibina、Docker、Vue等,都是开发者十分需要掌握的技术。有没有一个全面而又实际的项目,能把这...
- 腾讯云国际站:哪些工具能实现可视化运维?
-
本文由【云老大】TG@yunlaoda360撰写开源工具Grafana:开源的可视化平台,可与Prometheus、Elasticsearch、MySQL等多种数据源集成,将复杂监控数据转化...
- 系统稳定性保障全流程实战:事前、事中、事后 Java 代码详解
-
在互联网架构中,系统稳定性是生命线。本文基于“事前预防、事中管控、事后复盘”三阶段模型,结合Java实战代码,深度解析如何构建高可用系统,让你的服务稳如磐石!一、事前:未雨绸缪,筑牢防线1.发...
- Java面试题:拆分微服务应该注意哪些地方方,如何拆分?
-
在拆分微服务时,需要综合考虑业务、技术和组织等多方面因素,以下是关键注意事项及拆分策略的详细说明:一、拆分注意事项1.业务边界清晰化单一职责原则:每个服务应专注于单一业务能力,例如订单服务仅处理订单...
- 软件性能调优全攻略:从瓶颈定位到工具应用
-
性能调优是软件测试中的重要环节,旨在提高系统的响应时间、吞吐量、并发能力、资源利用率,并降低系统崩溃或卡顿的风险。通常,性能调优涉及发现性能瓶颈、分析问题根因、优化代码和系统配置等步骤,调优之前需要先...
- Docker Compose实战,多容器协同编排的利器,让开发部署更高效!
-
开篇导读你是否有过这样的经历?启动一个项目,数据库、Redis、Web服务得一个个敲dockerrun?想让别人复现你的开发环境,却得发一堆复杂的启动命令?明明都是容器,为什么不能“一键启动”所...
- 如何设计Agent的记忆系统(agent记忆方法)
-
最近看了一张画Agent记忆分类的图我觉得分类分的还可以,但是太浅了,于是就着它的逻辑,仔细得写了一下在不同的记忆层,该如何设计和选型先从流程,作用,实力和持续时间的这4个维度来解释一下这几种记忆:1...
- 不了解业务和技术术语怎么做好产品和项目?
-
基础技术术语术语分类解释API开发技术应用程序接口,不同系统间数据交互的协议(如支付接口、地图接口)。SDK开发工具软件开发工具包,包含API、文档和示例代码,帮助快速接入服务。RESTfulAPI...
- Docker 架构详解与核心概念实战图解:一文读懂容器的前世今生
-
不懂Docker架构,你只是“用容器的人”;理解了它的底层逻辑,才能成为真正的高手!在学习Docker之前,很多同学可能会陷入一个误区:“反正我用dockerrun就能跑起服务,架构这种...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (63)
- oracle批量插入数据 (62)
- oracle事务隔离级别 (53)
- oracle 空为0 (50)
- oracle主从同步 (55)
- oracle 乐观锁 (51)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)