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

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

off999 2025-02-19 13:23 10 浏览 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进阶教程:如何自定义异常(附电商库存管理案例)

在Python中,你可以使用异常(exceptions)来预期和处理那些干扰程序正常执行流程的错误。Python内置了许多常见的异常,例如ValueError、TypeError和KeyError,但...

Python 中使用try来处理异常的方法

六二,直方大,不习无不利。在学习python中会经常遇到各种异常事件;现归纳一下如何捕捉并处理这些异常;今天来给大家整理一下。一、异常的概念什么是异常?异常即是一个事件,该事件会在程序执行过程中发生,...

python入门-day3:异常处理(异常处理方法及流程python)

异常处理的内容,包括try、except、finally的用法,介绍常见异常类型,最后通过一个练习(处理用户输入的非法数字)帮你把知识点串起来。我会用简单易懂的语言,确保新手也能轻松掌握。Da...

16-Python的异常(python的异常类型及处理)

1-异常介绍1-2-什么是异常异常是程序运行时发生的错误或异常情况,它会中断正常的程序执行流程;Python使用异常处理机制来处理这些运行时错误。1-4-为什么要捕获异常异常会中断程序的执行;1-3-...

Python 异常处理详解(python中异常)

一、什么是异常?核心定义在程序运行过程中,当Python解释器检测到无法继续执行的操作时,会立即创建异常对象并中断当前流程。此时若不处理异常,程序将直接崩溃退出。典型场景与原理用户输入无效数据nu...

掌握这些 Python 异常处理技巧,代码稳如老狗!

在Python中,异常处理不仅可以帮助我们捕获和处理错误,还能让我们更清晰地了解错误发生的背景。1.异常层次结构Python内置了许多异常,我们在编程时可能会经常遇到,例如ZeroDivisi...

python异常处理机制最佳实践(python异常处理总结)

Python异常处理的最佳实践需要兼顾代码健壮性、可读性和性能。以下是经过工程验证的10个核心原则和技巧:一、精准捕获原则避免裸except禁止使用except:或exceptExce...

python之异常处理(python异常处理过程可以概括为三个步骤)

异常语法try:<代码块>except<异常类型>:<代码块>捕获通用异常try:<代码块>exceptExceptionas...

一天学一点,今天学习掌握Python:异常处理与文件操作全攻略

这一笔记记录了我学习python的异常和文件的操作,这也是针对Python异常和文件操作教程的进一步优化建议和注意事项:异常处理优化1.避免过度捕获异常o不要为了捕获异常而捕获异常,应根据实际需求...

新手学Python避坑,学习效率狂飙! 十二、Python 异常处理

异常处理系统分享在Python里,异常指的是程序运行期间出现的错误。当异常发生时,正常的程序流程会被中断,Python会抛出异常对象。为了防止程序因异常而崩溃,你可以使用异常处理机制捕获并处理这...

Python异常处理全攻略:从入门到精通,轻松应对代码“翻车”时刻

喜欢的条友记得关注、点赞、转发、收藏,你们的支持就是我最大的动力源泉。引言:异常处理——代码世界的“保险丝”在编程的世界里,错误和异常就像路上的“坑”,稍不留神就会让你的程序“翻车”。而异常处理,就是...

Python异常处理全面指南(python异常处理步骤)

Python异常处理完全指南异常处理是编写健壮程序的关键技术。Python提供了灵活的语法和丰富的内置异常类型,能够有效管理程序运行时的错误。以下是Python异常处理的全面指南:一、异常处理...

进阶突破python——异常处理机制(异常处理用什么语句python)

Python的异常处理机制是其健壮性设计的核心,通过清晰的语法结构和灵活的处理策略实现错误管理。以下从核心语法、异常对象、高级特性和最佳实践四个维度详解:一、核心语法结构Python使用try-...

Python基础编程——详细介绍Python的异常捕获示例代码

这篇文章主要为大家详细介绍了python的异常捕获,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助①捕捉一个异常捕捉一个异常以用0作为除数会得到Ze...

Python学习 -- 异常捕获技巧(python怎么捕获异常)

在编写Python代码时,异常处理是确保程序稳定性的关键。Python提供了灵活的异常捕获机制,包括try...except语句、try...except...else语句和try...except....

取消回复欢迎 发表评论: