百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

大厂双十一缓存架构设计_双十一技术架构

off999 2025-02-19 13:23 15 浏览 0 评论

1 缓存的应用

缓存(cache),原始意义是指访问速度比一般随机存储器(RAM)快的一种高速存储器,设置缓存是为了更好发

挥计算机系统的高性能。

1.1 缓存分类

1)应用级缓存

应用级缓存也就是我们平时写的应用程序中所使用的缓存。在平时程序中一般是按照如下操作流程来实现缓存的操作,首先张三用户读取数据库,并将读取的数据存入到缓存中,其他用户读取的时候,直接从缓存中读取,而不用查数据库,从而提高程序的执行速度和效率。

2)系统级别缓存

系统级别缓存是抛开我们应用程序之外硬件的缓存操作,例如某些CPU的缓存操作和如下图多级缓存流程类似,CPU在操作数据的时候,先读取1级缓存,1级缓存如果没有数据则读取2级缓存,2级缓存没有数据则读取3级缓存,3级缓存如果没有数据就直接从主存储器(存储指令和数据)读取数据。

1.2 缓存淘汰算法

数据缓存之后,为了避免缓存无限变大,我们需要对缓存进行管理,将一些不用的或者很少用的或者很久没更新的缓存淘汰掉,这里就需要用到一系列淘汰算法了,淘汰算法主要有如下几种:

1)FIFO(先进先出)

数据最先存入缓存,那么也将最先备淘汰掉。

2)LRU(最不常用数据)

判断缓存最近被使用的时间,时间最远被使用的缓存优先淘汰。

3)LFU(最少使用)

一段时间内,被使用的次数最少的数据,优先淘汰掉。

1.3 缓存应用场景

1)频繁查询数据缓存

有一些数据经常被访问,而且变更频率较低,实时性要求不高的数据,可以把它存储到缓存中,每次读取数据直接读缓存即可,从而提升数据的加载速度和系统的性能。

2)列表排序分页数据

一些变更频率较低查询频次较高的列表、分页、排序数据,可以存入到Redis缓存,每次查询分页或者排序的时候,直接从Redis缓存中获取。

3)计数器

网站中用于统计访问频次、在线人数、商品抢购次数等,也可以使用缓存来实现。

4)详情内容

站点中,资讯内容、商品详情等较大变更频率又低的内容,可以采用缓存来加速数据的读取,降低IO操作。

5)分布式Session

实现会话共享的时候,可以使用Session来存储需要共享的会话,从而节省内存空间。

6)热点排名

我们可以使用ZSet来存储热数据,并实现热点数据的排名。

7)发布订阅

用Redis也可以实现发布与订阅,但不推荐,推荐用MQ。

8)分布式锁

可以使用Redisson结合Redis实现分布式锁,Redis实现的分布式锁效率极高,得到了市场的广泛使用。

1.4 微服务架构缓存的使用

在微服务架构中,会大量使用到缓存,如上图:

2 高并发站点缓存技术选型

双十一大促销活动有很多技术挑战,而最大的挑战之一就是高并发,而应对高并发的最有效手段之一就是分布式缓存,分布式缓存不仅仅是缓存要显示的数据这么简单,还可以在限流、队列削峰、高速读写、分布式锁等场景发挥重大作用。分布式缓存可以说是解决高并发场景的一头野兽。

2.1 双十一活动大促分析

双十一无论抢红包、商品秒杀、抢优惠券,并发量都是超高,流量可以说是平时几倍乃至几十倍,对服务器造成的压力也几何数字增长,因此双十一必须要考虑各种场景的技术解决方案。

面对双十一巨大流量涌入,需要解决的问题我们做一个分析:

2.2 高性能利器-缓存

传统关系型数据库能处理的并发链接一般都很有限,如果优化的很优秀,并发链接量可高达几千,而一般公司对其优化的并不怎么乐观,很多公司的数据库并发链接量只控制在了几百。单纯用数据库实现数据的高效存取是存在很大挑战和问题的,因此一定要找一种方式或者软件取代传统关系型数据库的存取功能。

针对传统关系型数据库存取性能瓶颈,我们可以采用高性能的非关系型数据库来取代传统关系型数据库,这里以当前主流的分布式缓存技术Redis为例,可以实现单机每秒读10万次以上,写每秒8万次以上的能力,远超关系型数据库,因此解决传统关系型数据库的存取能力,我们可以用非关系型数据库来优化甚至取代关系型数据库。

2.3 缓存性能对比

当前主流的缓存技术有 Memcached 、 Tair 、 Redis ,这几款分布式缓存都各有优缺点,大家可以根据不同的使用场景来选择使用。

Memcached:

Redis:(推荐)

Tair:

3 双十一缓存架构设计

一谈到缓存架构,很多人想到的是Redis,但其实整套体系的缓存架构并非只有Redis,而应该是多个层面多个软件结合形成一套非常良性的缓存体系。比如咱们的缓存架构设计就涉及到了多个层面的缓存软件。

3.1 缓存架构设计

上图缓存架构体系借鉴了一线大厂京东缓存架构设计经验,并在京东设计方案上进行了优化,让它更符合一线厂家的需要。上述架构图综合了多种缓存和多层面的缓存设计,从前端页面缓存到代理服务器lvs和nginx缓存,以及后端服务redis缓存,包括缓存数据同步等。

对上述架构,我们来个宏观解说:

3.2 Redis集群高级应用

这里安装6个redis,配置如下:

小知识点(Redis6.0.5):

注意安装Redis6.x的时候一定要切换到gcc7再安装,否则会报如下错误:

切换语法:

3.2.1 Redis版本特性介绍

Redis我们采用Redis6.0.5最新版本,它有很多新特性,我们这里对Redis每个版本的特性介绍一下:

Redis2.6

Redis2.8

Redis3.0(里程碑)

Redis3.2

Redis4.0

Redis5.0

Redis6.0.5(里程碑)

3.2.2 Redis集群配置

现在安装对应的应用软件一般都推荐使用Docker容器,我们这里也不例外,直接使用Docker容器进行安装,安装大概要分这几个步骤:

配置Redis信息

创建 redis-cluster.tmpl 配置Redis信息(redis.conf)

Redis创建配置

创建 redis.sh 配置需要创建的 Redis 集群

这里涉及到了一个网络的定义 redis-net ,代码如下:

移除脚本创建

创建 stop.sh 脚本,用于停止Redis容器,并且移除对应容器

脚本授权:给 redis.sh 和 stop.sh 添加可执行权限:

执行脚本开始安装Redis节点,并进入到 /usr/local/bin 目录下执行 redis-cli 创建集群关联:

--cluster-replicas 表示有一个主有几个slave。

安装好了后,我们链接Redis效果如下:

3.2.3 主从复制

我们先来理解下主从同步,如下图:

我们可以用 DesktopManager 链接Redis集群,并测试数据,往redis集群添加2条数据,可以明显看到主从效果,效果如下:

上面是我们集群时随机创建的从节点,如果手动给指定节点添加从节点也是可以实现的,我们这里实现给 7001 添加一个从节点。

3.2.4 集群扩容收容

上面虽然创建了主从复制,但如果手动给节点添加一个从节点,有可能添加从节点,也有可能添加从节点,这是我们想要干的。接下来我们给集群节点添加指定的从节点。

我们安装 7007 、 7008 、 7009 几个Redis节点,然后将 7007 和 7008 作为主节点,添加到集群中, 7009 作为从节点添加到集群中。

基于Docker安装Redis这里编写了一个脚本,安装脚本 redis-port.sh 如下:

我们执行 redis-port.sh 脚本,实现 7007,7008,7009 节点安装。

添加课执行权限:

查看集群状态

主节点查看:

主节点状态信息如下:

从节点查看:

从上面信息我们可以看出集群关系:

3.2.4.1 添加集群主节点

我们需要给集群节点添加一个主节点,我们需要将 192.168.211.141:7007 节点添加到 192.168.211.141:7001 节点所在的集群中,并且添加后作为主节点,添加命令行如下:

命令说明:

执行命令后,效果如下:

此时我们可以进入到集群节点之一查看此时的集群状态,我们进入到 7002 节点中输入 cluster node 查询,操作方法如下:

效果如下:

3.2.4.2 哈希槽分配

从上面的集群节点信息我们可以看出一个问题,其他主节点都有一串数字范围,而刚才添加的 7007 节点没有这段数字范围,这和Redis集群原理有关系,我们来讲解一下集群的原理,然后实现新增节点哈希槽(这段数字范围)的分配。

Redis原理:

从原理上分析,因为之前 7001,7002,7003 已经瓜分了16384个哈希槽,所以再增加一个新节点是没有剩余哈希槽分配的,所以新增的 7007 节点没有分配到哈希槽。我们只能重新分配哈希槽,才能让新增节点分配到一定的哈希槽,重新分配哈希槽后,我们还要考虑之前其他Redis节点中的数据迁移。

重新分配Hash槽

我们将 7001,7002,7003 中的 100 个哈希槽挪给 7007 ,命令如下:

命令说明:

参数说明:

将100个哈希槽挪给7007后,我们查询下节点信息:

效果如下

3.2.4.3 添加集群从节点

我们需要往集群中给 7007 节点添加一个从节点 7008 ,添加从节点的主要目的是提高高可用,防止主节点宕机后该节点无法提供服务。添加从节点命令如下:

命令说明:

参数说明:

执行命令后,效果如下:

集群信息查看:

3.2.4.4 缩容

1)数据迁移

2)哈希槽迁移

3)从节点删除

4)主节点删除


在真实生产环境中,我们也会跟着我们的业务和环境执行缩容处理,比如双十一过后,流量没有那么大了,我们往往会缩容处理,服务器开销。

Redis实现缩容,需要哈希槽重新分配,将需要移除的节点所分配的所有哈希槽值分配给其他需要运行工作的节点,还需要移除该节点的从节点,然后再删除该节点。

移除从节点

移除 7007 的从节点 7008 ,命令如下:

参数说明:

删除后,我们再来查看集群节点,此时再无7008节点。

迁移Master的Slot

我们需要将 7007 节点的哈希槽迁移到 7001,7002,7003 节点上,仍然用上面用过的 redis-cli --cluster reshard语法,命令如下:

第1次迁移:

命令说明:

效果如下:

查看集群节点:

我们再次迁移其他哈希槽到其他节点,将剩余的哈希槽迁移到7002和7003去。

第2次迁移:

第3次迁移:

集群状态查询:

删除7007主节点

删除节点命令如下:

效果如下:

集群节点查看:

3.3 Redis Sentinel

哨兵是用来解决redis高可用性的,可以监控集群中主从的变化,然后进行故障转移。

3.3.1 哨兵讲解

一套合理的监控机制是Sentinel节点判定节点不可达的重要保证,Redis Sentinel通过三个定时监控任务完成对各个节点发现和监控。

周期10秒监控

每隔10秒,每个Sentinel节点会向主节点和从节点发送info命令获取最新的主从结构,该命令有3个作用:

周期2秒监控

每隔2秒,每个Sentinel节点会向Redis数据节点的 __sentinel__:hello 频道上发送该Sentinel节点对于主节点的判断以及当前Sentinel节点的信息 ,同时每个Sentinel节点也会订阅该频道,来了解其他 Sentinel节点以及它们对主节点的判断。

该定时任务主要有2个作用:

周期1秒监控

每隔1秒,每个Sentinel节点会向主节点、从节点、其余Sentinel节点发送一条ping命令做一次心跳检测,来确认这些节点当前是否可达,从而实现检查每个节点的健康状态。

Redis-Sentinel是用于管理Redis集群,主要执行如下任务:

执行流程

哨兵来实现Redis高可用有这5个流程:

状态说明

节点状态分为:ok、主观下线、客观下线。

正常(ok):就是节点在线,能够正常响应哨兵的检测和命令。

主观下线(sdown):指单个哨兵,发现主节点在down-after-milliseconds时间内无正确响应,做出的状态判断。

客观下线(odown):指多个哨兵对一个主节点做了sdown判断后,互相使用is-master-down-by-addr命令交流后,做出的节点已经下线的判断。


4 Nginx缓存

为了提升网站的整体性能,我们一般会采用缓存,从宏观层面来说,会采用浏览器缓存和后端缓存,Nginx处于Web网站的服务最外层,而且支持浏览器缓存配置和后端数据缓存,用它来做部分数据缓存,效率更高。

Web缓存是可以自动保存常见文档副本的HTTP 设备。当Web请求抵达缓存时,如果本地有“已缓存的”副本,就可以从本地设备而不是服务器中提取这个文 档。

4.1 OpenRestry安装

OpenResty? 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、 Web 服务和动态网关。

OpenResty 通过lua脚本扩展 nginx 功能,可提供负载均衡、请求路由、安全认证、服务鉴权、流量控制与日志监控等服务。

OpenResty? 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样, Web 开发人员和系统工程师可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10K 乃至 1000K 以上单机并发连接的高性能 Web 应用系统。

关于 OpenRestry 的学习,大家可以参考: http://openresty.org/cn/

安装依赖库

下载安装包

解压安装

安装完成后,在
/usr/local/openrestry/nginx 目录下是安装好的nginx。

4.2 浏览器缓存

客户端侧缓存一般指的是浏览器缓存、app缓存等等,目的就是加速各种静态资源的访问,降低服务器压力。

我们通过配置Nginx设置网页缓存信息,从而降低用户对服务器频繁访问造成的巨大压力。我们先配置一个案例,再基于案例去讲解Nginx缓存。

4.2.1 Nginx Web缓存配置

nginx 提供了 expires 、 etag 、 if-modified-since 指令来进行浏览器缓存控制。我们使用 expires 来配置Nginx对网页的缓存。

1)上传html

将1.html上传到服务器的 /usr/local/server/html 目录下。

2)配置nginx

修改
/usr/local/openrestry/nginx/conf/nginx.conf 文件,配置如下:

过期时间配置说明

第一次请求 <
http://192.168.211.141/1.html>

第二次请求 <
http://192.168.211.141/1.html>

4.2.2 Http缓存控制头

参数说明:

4.3 代理缓存

用户如果请求获取的数据不是需要后端服务器处理返回,如果我们需要对数据做缓存来提高服务器的处理能力,我们可以按照如下步骤实现:

4.3.1 proxy_cache

proxy_cache 是用于 proxy 模式(一般也可称为反代)的缓存功能,proxy_cache 在 Nginx 配置的 http 段、server段(location 段)中分别写入不同的配置。http 段中的配置用于定义 proxy_cache 空间,server 段中的配置用于调用 http 段中的定义,启用对 server 的缓存功能。

属性使用说明

proxy_cache_path:

proxy_cache:

proxy_cache_valid:

proxy_cache_min_uses:

proxy_cache_lock:

proxy_cache_key:

'

4.3.2 缓存操作

我们在 nginx.conf 中添加如下配置:'

此时
/usr/local/openresty/nginx/cache 目录下只有1个temp文件夹。

我们执行3次请求 <
http://192.168.211.141/user/wangwu> ,可以发现此时多了一些其他目录,这些目录就是存储每个请求对应的缓存

相关推荐

Python钩子函数实现事件驱动系统(created钩子函数)

钩子函数(HookFunction)是现代软件开发中一个重要的设计模式,它允许开发者在特定事件发生时自动执行预定义的代码。在Python生态系统中,钩子函数广泛应用于框架开发、插件系统、事件处理和中...

Python函数(python函数题库及答案)

定义和基本内容def函数名(传入参数):函数体return返回值注意:参数、返回值如果不需要,可以省略。函数必须先定义后使用。参数之间使用逗号进行分割,传入的时候,按照顺序传入...

Python技能:Pathlib面向对象操作路径,比os.path更现代!

在Python编程中,文件和目录的操作是日常中不可或缺的一部分。虽然,这么久以来,钢铁老豆也还是习惯性地使用os、shutil模块的函数式API,这两个模块虽然功能强大,但在某些情况下还是显得笨重,不...

使用Python实现智能物流系统优化与路径规划

阅读文章前辛苦您点下“关注”,方便讨论和分享,为了回馈您的支持,我将每日更新优质内容。在现代物流系统中,优化运输路径和提高配送效率是至关重要的。本文将介绍如何使用Python实现智能物流系统的优化与路...

Python if 语句的系统化学习路径(python里的if语句案例)

以下是针对Pythonif语句的系统化学习路径,从零基础到灵活应用分为4个阶段,包含具体练习项目和避坑指南:一、基础认知阶段(1-2天)目标:理解条件判断的逻辑本质核心语法结构if条件:...

[Python] FastAPI基础:Path路径参数用法解析与实例

查询query参数(上一篇)路径path参数(本篇)请求体body参数(下一篇)请求头header参数本篇项目目录结构:1.路径参数路径参数是URL地址的一部分,是必填的。路径参...

Python小案例55- os模块执行文件路径

在Python中,我们可以使用os模块来执行文件路径操作。os模块提供了许多函数,用于处理文件和目录路径。获取当前工作目录(CurrentWorkingDirectory,CWD):使用os....

python:os.path - 常用路径操作模块

应该是所有程序都需要用到的路径操作,不废话,直接开始以下是常用总结,当你想做路径相关时,首先应该想到的是这个模块,并知道这个模块有哪些主要功能,获取、分割、拼接、判断、获取文件属性。1、路径获取2、路...

原来如此:Python居然有6种模块路径搜索方式

点赞、收藏、加关注,下次找我不迷路当我们使用import语句导入模块时,Python是怎么找到这些模块的呢?今天我就带大家深入了解Python的6种模块路径搜索方式。一、Python模块...

每天10分钟,python进阶(25)(python进阶视频)

首先明确学习目标,今天的目标是继续python中实例开发项目--飞机大战今天任务进行面向对象版的飞机大战开发--游戏代码整编目标:完善整串代码,提供完整游戏代码历时25天,首先要看成品,坚持才有收获i...

python 打地鼠小游戏(打地鼠python程序设计说明)

给大家分享一段AI自动生成的代码(在这个游戏中,玩家需要在有限时间内打中尽可能多的出现在地图上的地鼠),由于我现在用的这个电脑没有安装sublime或pycharm等工具,所以还没有测试,有兴趣的朋友...

python线程之十:线程 threading 最终总结

小伙伴们,到今天threading模块彻底讲完。现在全面总结threading模块1、threading模块有自己的方法详细点击【threading模块的方法】threading模块:较低级...

Python信号处理实战:使用signal模块响应系统事件

信号是操作系统用来通知进程发生了某个事件的一种异步通信方式。在Python中,标准库的signal模块提供了处理这些系统信号的机制。信号通常由外部事件触发,例如用户按下Ctrl+C、子进程终止或系统资...

Python多线程:让程序 “多线作战” 的秘密武器

一、什么是多线程?在日常生活中,我们可以一边听音乐一边浏览新闻,这就是“多任务处理”。在Python编程里,多线程同样允许程序同时执行多个任务,从而提升程序的执行效率和响应速度。不过,Python...

用python写游戏之200行代码写个数字华容道

今天来分析一个益智游戏,数字华容道。当初对这个游戏颇有印象还是在最强大脑节目上面,何猷君以几十秒就完成了这个游戏。前几天写2048的时候,又想起了这个游戏,想着来研究一下。游戏玩法用尽量少的步数,尽量...

取消回复欢迎 发表评论: