专栏名称: macrozheng
专注Java技术分享,解析优质开源项目。涵盖SpringBoot、SpringCloud、Docker、K8S等实用技术,作者Github开源项目mall(50K+Star)。
目录
相关文章推荐
51好读  ›  专栏  ›  macrozheng

小白眼中的Redis。。。

macrozheng  · 公众号  · 后端 科技自媒体  · 2024-12-10 10:32

主要观点总结

本文介绍了如何通过添加Redis缓存服务来解决商品服务面对大流量查询时的问题,通过本地缓存和远程缓存的方式优化查询性能,并提供了Redis的多种数据类型支持、内存过期策略、缓存淘汰机制、持久化能力等相关知识的介绍。同时,推荐了一个电商系统开源项目mall及其视频教程。

关键观点总结

关键观点1: Redis作为远程字典服务解决大流量查询问题

通过添加Redis缓存服务,将mysql中的数据存放到内存中,提高查询性能,解决mysql顶不住大流量查询的问题。

关键观点2: Redis支持多种数据类型和缓存策略

Redis除了支持字符串类型的缓存,还提供了先进先出的队列List、用于去重的Set类型、用于排行榜的ZSet等数据结构。同时,还提供了内存过期策略和缓存淘汰机制,以优化内存使用。

关键观点3: Redis的持久化能力

Redis通过RDB和AOF两种方式实现数据的持久化,确保服务重启后数据不会丢失。

关键观点4: 推荐电商系统开源项目mall及其视频教程

文章推荐了一个电商系统开源项目mall,并提供了详细的视频教程。该项目涵盖了电商系统的各个模块,包括购物车、订单、支付等,同时采用了最新的微服务项目实战技术和Kubernetes容器化部署。


正文

Boot+Cloud项目学习: macrozheng.com

是一个程序员,你维护了一个 商品服务,它背后直连 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 身上,疼得它嗷嗷叫。







请到「今天看啥」查看全文