企业级NoSQL数据库Redis

1.浏览器缓存过期机制

1.1 最后修改时间 last-modified

浏览器缓存机制是优化网页加载速度和减少服务器负载的重要手段。以下是关于浏览器缓存过期机制、Last-ModifiedETag 的详细讲解:

一、Last-Modified 头部

  • 定义Last-Modified 表示服务器上资源的最后修改时间。

  • 作用:用于资源的条件请求,帮助浏览器判断缓存的资源是否是最新的。

  • 工作流程

    1. 浏览器第一次请求资源时,服务器返回资源内容和 Last-Modified 时间。

    2. 下次请求同一资源时,浏览器发送 If-Modified-Since 头部,值为之前的 Last-Modified 时间。

    3. 服务器比较资源的当前修改时间与 If-Modified-Since的值:

      • 如果资源未修改,返回 304 Not Modified,浏览器继续使用缓存。
      • 如果资源已修改,返回新的资源内容和更新后的 Last-Modified 时间。
  • 示例

Last-Modified: Wed, 21 Oct 2023 07:28:00 GMT

二、ETag 头部

  • 定义ETag(Entity Tag)是服务器为资源生成的唯一标识符,通常是资源内容的哈希值或版本号。

  • 作用:比 Last-Modified 更加精确,用于验证资源是否变化。

  • 工作流程

    1. 浏览器第一次请求资源时,服务器返回资源内容和 ETag 值。

    2. 下次请求同一资源时,浏览器发送 If-None-Match 头部,值为之前的 ETag

    3. 服务器比较当前资源的 ETagIf-None-Match的值:

      • 如果 ETag 未变化,返回 304 Not Modified,浏览器继续使用缓存。
    • 如果 ETag 变化,返回新的资源内容和新的 ETag 值。
  • 示例

ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

五、Last-Modified vs ETag

  • 精确度
    • Last-Modified 仅记录最后修改时间,可能无法检测到在同一秒内的多次修改。
    • ETag 通常基于内容的哈希值,能够更精确地检测到任何变化。
  • 性能
  • 生成 ETag 可能需要更多的计算资源,尤其是在大规模资源或高频请求的情况下。
  • Last-Modified 相对简单,性能开销较小。
  • 使用场景
    • 对于静态资源,ETag 更加适用。
    • 对于动态资源,可以结合 Last-Modified 和其他缓存策略使用。

六、最佳实践

  1. 合理设置缓存策略
    • 对于不经常变化的静态资源,设置较长的 max-age 以充分利用缓存。
    • 对于经常变化的资源,使用较短的 max-age 或结合验证机制。
  2. 使用 ETagLast-Modified
    • 同时使用两者可以提供更可靠的缓存验证,但需注意服务器的性能开销。
  • 如果服务器性能有限,可以选择只使用其中一个。
  1. 版本化资源
    • 通过在资源URL中包含版本号(如 style.v1.css),可以在资源更新时强制浏览器下载新版本,避免缓存问题。

七、总结

浏览器缓存机制通过多种HTTP头部字段控制资源的缓存和过期,Last-ModifiedETag 是其中重要的验证手段。合理配置这些头部字段,可以显著提升网页性能,优化用户体验,同时有效管理服务器资源。

第一次访问

image-20241216144110944

第二次访问

image-20241216144252162

1.2 Etag 标记

但是如果访问的时间一样的,怎么办?If-Modefied精确到的是秒,要知道的是,计算机一秒中可以干好多事的,比如一秒中修改上千次的图片

# 使用 touch 模拟访问时间是一样的(移走1.jpeg,在重新上传一张图片,重命名为1.jpeg)
[root@Rocky9.4 html]#touch -t 202407020931.48 1.jpeg

第一次访问

第一次访问是由于我将时间设置成一样了,但是因为服务器返回的Etag是新的,而浏览器保存的还是旧的,所以Etag不一致,所以返回状态码是200

image-20241216143352281

第二次访问

第二次访问,Etag也统一了,所以返回了状态码304

image-20241216145149331

1.3 过期时间 expires 和 Cache-Control

一、浏览器缓存机制概述

浏览器缓存通过在本地存储网页资源(如HTML、CSS、JavaScript、图片等),避免每次访问网页时都从服务器重新下载这些资源,从而加快页面加载速度,提高用户体验,同时减少服务器带宽的使用。

明白了,你希望更详细地了解浏览器缓存中的 ExpiresCache-Control 头部,以及它们之间的关系和具体应用。以下是更深入的讲解:

二、Expires 头部

1. 定义与作用
  • Expires 是一个HTTP响应头,用于指定资源的绝对过期时间。它告诉浏览器在指定的时间之前,可以直接从缓存中使用该资源,而无需向服务器重新请求。
2. 格式
  • Expires 的值是一个绝对的HTTP日期和时间,格式为:Wdy, DD Mon YYYY HH:MM:SS GMT

示例

Expires: Wed, 21 Oct 2025 07:28:00 GMT
3. 使用场景
  • 适用于静态资源,如图片、CSS、JavaScript文件,这些资源不经常变化。
  • 适合设置较长的缓存时间,减少浏览器对服务器的请求频率,提升加载速度。
4. 缺点
  • 使用绝对时间,可能受客户端和服务器时间不同步的影响。
  • 当资源更新时,若不改变 Expires,可能导致浏览器继续使用过期的缓存,出现内容不一致的问题。

三、Cache-Control 头部

1. 定义与作用
  • Cache-Control 是一个更为灵活和强大的HTTP响应头,用于控制缓存策略。它可以替代或补充 Expires 头部,提供更精确的缓存控制。
2. 常用指令
  • max-age=秒数:指定资源在多少秒内被认为是新鲜的。max-age 的优先级高于 Expires

示例

Cache-Control: max-age=3600
  • no-cache:资源必须在使用前重新验证(即使资源没有过期)。

示例

Cache-Control: no-cache
  • no-store:禁止任何形式的缓存,既不存储请求信息,也不存储响应信息。

示例

Cache-Control: no-store
  • public:响应可被任何缓存区缓存,包括浏览器和中间缓存(如CDN)。

示例

Cache-Control: public
  • private:响应仅为单个用户缓存,不能被共享缓存(如CDN)缓存。

示例

Cache-Control: private
  • must-revalidate:一旦资源过期,必须向服务器验证其有效性。

示例

Cache-Control: must-revalidate
  • proxy-revalidate:与 must-revalidate 类似,但仅适用于共享缓存。

示例

Cache-Control: proxy-revalidate
3. 使用场景
  • 动态资源:可以灵活设置缓存策略,如需要频繁更新但又希望利用缓存提升性能的资源。
  • 细粒度控制:通过组合多个指令,实现更复杂的缓存策略。
4. 与 Expires 的关系
  • 优先级:当同时存在 Cache-Control: max-ageExpires 时,Cache-Control 优先级更高。
  • 推荐使用:现代浏览器和服务器更推荐使用 Cache-Control,因为它更灵活且不依赖绝对时间。

四、ExpiresCache-Control 的对比

特性 Expires Cache-Control
类型 绝对时间 相对时间及其他缓存指令
格式 HTTP日期格式 指令列表
优先级 低于 Cache-Control 高于 Expires
灵活性 较低,只有一个绝对过期时间 高,可以组合多种指令控制缓存行为
推荐使用场景 主要用于向后兼容旧浏览器 现代Web应用的首选缓存控制方式

五、实际应用示例

1. 设置长时间缓存(适用于不经常变化的静态资源)
Cache-Control: public, max-age=31536000
Expires: Wed, 21 Oct 2025 07:28:00 GMT
  • 解释:资源可以被公共缓存(如CDN)缓存,且在1年内(31536000秒)不需要重新验证。
2. 设置短时间缓存,需重新验证(适用于可能会频繁更新的资源)
Cache-Control: no-cache
  • 解释:浏览器每次使用缓存前必须向服务器验证资源是否有更新。
3. 禁止缓存(适用于敏感数据)
Cache-Control: no-store
  • 解释:禁止任何形式的缓存,确保每次请求都从服务器获取最新数据。

六、结合 ETagLast-Modified 使用缓存验证

即使设置了 Cache-ControlExpires,浏览器在某些情况下仍可能需要验证缓存资源的有效性。此时,ETagLast-Modified 提供了有效的验证机制:

  • ETag:提供资源的唯一标识符,确保缓存的资源与服务器上的一致。
  • Last-Modified:记录资源的最后修改时间,供浏览器进行条件请求。

示例

Cache-Control: max-age=3600, must-revalidate
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
Last-Modified: Wed, 21 Oct 2023 07:28:00 GMT

七、最佳实践

  1. 优先使用 Cache-Control
  • 由于其灵活性和优先级,现代Web开发中应优先配置 Cache-Control 头部。
  1. 合理设置 max-age
  • 根据资源的更新频率,合理设置缓存时间。静态资源可以设置较长时间,动态资源设置较短时间或不缓存。
  1. 结合使用 ETagLast-Modified
  • 提供双重验证机制,确保缓存的资源始终是最新的。
  1. 版本化静态资源
  • 通过在资源URL中添加版本号(如 style.v1.css),确保资源更新时浏览器能够获取到最新版本,避免缓存问题。
  1. 使用CDN
  • 配合缓存头部,利用内容分发网络(CDN)提升全球范围内的资源加载速度,并有效管理缓存策略。

八、总结

  • ExpiresCache-Control 都用于控制资源的缓存和过期,但 Cache-Control 提供了更高的灵活性和优先级。
  • ETagLast-Modified 是用于缓存验证的强大工具,确保浏览器使用最新的资源。
  • 最佳实践 是结合使用这些HTTP头部,合理设置缓存策略,提升Web应用的性能和用户体验。

1.4 CDN

CDN(内容分发网络,Content Delivery Network)是一种通过将内容复制并缓存到全球多个地理位置的服务器上,从而加速用户访问速度的技术。它主要的目的是提高网站或应用的性能、稳定性、可扩展性,同时减少服务器负载和带宽消耗。

一、CDN的工作原理

CDN的核心思想是将网站的静态资源(如HTML文件、CSS文件、JavaScript、图片、视频等)缓存到分布在全球的边缘服务器(Edge Servers)上。当用户请求访问某个资源时,CDN会根据用户的地理位置,选择距离用户最近的服务器提供资源,从而减少加载时间和提高访问速度。

1. 资源分发与缓存
  • 资源分发:当你将资源上传到CDN服务时,CDN提供商会将这些内容分发到位于世界各地的数据中心。
  • 缓存:CDN的服务器会将常用的静态内容缓存到本地存储中,当有新的请求时,如果内容已经存在并且没有过期,则直接返回缓存的内容。
2. 边缘服务器与原始服务器
  • 边缘服务器(Edge Server):这些是部署在全球各地的服务器,负责将资源提供给终端用户。用户访问时,通常会被路由到离他们最近的边缘服务器,以减少延迟。
  • 原始服务器(Origin Server):原始服务器是网站的源服务器,存储网站的所有内容。如果CDN的边缘服务器没有缓存某个请求的内容,它会从原始服务器获取并返回给用户。
3. 缓存策略

CDN通常会使用一些缓存策略来决定哪些内容需要缓存,以及缓存多久。常见的缓存策略包括:

  • 缓存时间(TTL,Time to Live):决定缓存的有效期。例如,静态资源如图片、CSS文件可能会缓存较长时间,而动态内容可能缓存较短时间。
  • 缓存控制(Cache-Control):通过设置HTTP头来控制缓存行为(如 max-ageno-cache)。
  • 动态内容缓存:CDN一般针对动态内容(如用户特定数据、实时信息)使用不同的缓存策略,可能会使用“按需缓存”或“低过期时间”的方式进行处理。
4. 智能路由与负载均衡

CDN通常会根据多个因素(如地理位置、网络负载、带宽等)选择最优的边缘服务器来响应用户请求。这一过程称为智能路由或负载均衡。通过此方式,CDN能够确保用户始终通过最快的路径获取到资源。

二、CDN的优势

  1. 提高加载速度
    • 减少延迟:通过将内容分发到全球多个节点,用户总是能够从离自己最近的节点获取资源,从而大幅减少延迟,提高加载速度。
    • 更高的可用性:通过分布式缓存,用户能够在多个服务器之间获取资源,即使某个服务器出现故障,也不会影响服务的可用性。
  2. 减轻原始服务器负载
    • CDN缓存了大量静态内容,减少了原始服务器的直接负担,降低了带宽使用和处理请求的压力。
  3. 提升网站的可扩展性
    • CDN帮助网站应对流量激增,能够在不同地区和时段自动调整资源的分配和流量管理,提供更好的扩展性。
  4. 增强网站的安全性
    • DDoS防护:许多CDN提供DDoS攻击防护,能够通过分布式架构分担攻击流量,从而减轻原始服务器的压力。
    • SSL加密:CDN服务提供SSL证书支持,帮助加密数据传输,提升安全性。
  5. 节省带宽成本
    • 通过减少从原始服务器到客户端的流量,CDN有助于降低带宽费用,尤其是对于全球性网站。
  6. 高可用性和容错性
    • CDN通过将资源缓存到多个节点,提升了资源的冗余度。在某个节点出现故障时,流量可以被自动引导到其他正常工作的节点,保证网站的高可用性。

三、CDN的类型

  1. 静态内容CDN
    • 主要缓存静态内容,如图片、JavaScript文件、CSS文件等。通过将这些内容缓存到多个位置,能够加速资源加载速度。
  2. 动态内容CDN
    • 动态内容指的是根据用户请求生成的内容,比如数据库查询结果或用户个性化信息。动态内容通常不缓存,但现代CDN提供商提供了对动态内容的优化方案,通过智能缓存策略加速动态内容的加载。
  3. 直播和视频流CDN
    • 专门用于视频流、直播视频内容的传输,优化了大带宽视频数据的分发和传输。常见的技术包括流媒体协议如 HLS(HTTP Live Streaming)和 DASH(Dynamic Adaptive Streaming over HTTP)。
  4. 边缘计算CDN
    • 这种类型的CDN不仅提供缓存功能,还支持在边缘服务器上执行计算任务。它能够在靠近用户的地方处理请求,提高性能和降低延迟。

四、CDN的工作流程

  1. 资源上传到CDN
    • 将网站的静态资源上传到CDN供应商的服务器。资源可能会分发到多个全球节点进行缓存。
  2. 用户请求访问资源
    • 用户访问网页时,浏览器向CDN发起请求。CDN会根据用户的地理位置,智能选择离用户最近的服务器响应请求。
  3. 缓存命中与未命中
    • 如果边缘服务器已缓存该资源(缓存命中),CDN直接返回缓存的内容。
    • 如果缓存过期或没有缓存该资源(缓存未命中),CDN会向原始服务器请求资源,并将返回的资源缓存起来供后续用户使用。
  4. 返回资源给用户
    • 一旦缓存的资源通过CDN的边缘节点返回给用户,用户的浏览器会在本地缓存该资源,下次访问时,直接从浏览器本地获取。

五、CDN的服务提供商

目前,全球有多个主要的CDN服务提供商,最知名的包括:

  1. Cloudflare
    • 提供免费和收费的CDN服务,支持全球分布的边缘节点,提供DDoS防护和Web应用防火墙(WAF)。
  2. Akamai
    • 全球领先的CDN供应商,服务覆盖范围广,适用于大规模企业和高流量网站,提供强大的内容加速和安全功能。
  3. Amazon CloudFront
    • AWS提供的CDN服务,能够与AWS的其他服务(如S3、EC2等)无缝集成,提供高可扩展性和灵活性。
  4. Fastly
    • 以高性能为特点,支持即时缓存清除和高效的动态内容传输,适用于对延迟要求极高的应用。
  5. KeyCDN
    • 提供较为简单和成本效益高的CDN解决方案,适用于中小型网站。

六、CDN的优化策略

  1. 合理设置缓存过期时间
    • 根据内容的更新频率,合理设置缓存过期时间(TTL),避免缓存过期导致频繁访问原始服务器。
  2. 使用分布式缓存
    • 利用CDN的全球节点分布,将内容缓存到多个节点,从而提供更好的负载均衡和冗余。
  3. 压缩和优化内容
    • 对资源进行压缩(如图片、CSS、JavaScript等),减少传输的数据量,提高加载速度。
  4. 结合HTTPS加密
    • 使用CDN的SSL证书加密功能,为网站提供HTTPS支持,提升数据传输的安全性。

七、总结

CDN是一种通过将网站内容分发到全球多个节点,减少延迟、提高加载速度、减轻服务器负载的技术。它不仅能加速资源的交付,还能提高网站的安全性、可用性和可扩展性。随着互联网应用的增长,CDN已成为优化网站性能和提供全球用户良好体验的重要工具。

1.4.1 用户请求CDN流程

用户请求CDN资源的流程可以分为几个步骤。这个流程涉及到用户如何向CDN发起请求,CDN如何决定从哪个服务器提供资源,以及缓存如何影响响应时间。以下是详细的用户请求CD能资源的流程:

一、请求流程概述

  1. 用户发起请求:用户的浏览器或应用程序向服务器请求某个资源(如图片、CSS、JavaScript文件等)。
  2. DNS解析:请求首先通过DNS解析,将资源的域名解析为CDN的IP地址。
  3. 路由到CDN边缘节点:用户的请求被路由到距离用户最近的CDN边缘节点。
  4. 边缘节点缓存检查:CDN的边缘节点检查缓存中是否已有该资源。
  5. 缓存命中或未命中:根据缓存的情况,决定是直接返回缓存的内容,还是从源服务器获取最新的资源。
  6. 返回资源给用户:资源通过边缘节点传输给用户,用户的浏览器接收并展示。

二、详细步骤

1. 用户发起请求

用户在浏览器中输入网址或点击链接时,浏览器会发起HTTP请求来请求某个资源。这些资源通常是静态文件,如HTML、CSS、JavaScript文件,或者图片、视频等媒体文件。

例如,用户请求资源:https://www.example.com/images/logo.png

2. DNS解析

用户请求的域名(如 www.example.com)会通过DNS解析,转化为一个IP地址。通常,这个域名已经指向CDN提供商的域名解析系统。

  • 传统方式:直接访问原始服务器的IP。
  • CDN方式:DNS解析返回的是CDN边缘服务器的IP,而不是源服务器的IP。

CDN提供商通常会在多个地理位置部署多个边缘节点(edge node),当请求发起时,DNS会返回离用户最近的CDN边缘节点的IP地址,确保请求被路由到最近的服务器。

3. 请求被路由到CDN边缘节点

DNS解析完成后,浏览器向CDN的边缘节点发送请求。CDN边缘节点是部署在全球各地的服务器,它们缓存了资源内容,能够快速响应用户请求。

CDN边缘节点的选择通常由以下因素决定:

  • 地理位置:用户的IP地址与边缘节点的地理位置之间的距离,尽可能选择距离用户最近的节点。
  • 网络负载:当前边缘节点的负载情况。如果某个节点过载,CDN会选择其他负载较低的节点。
4. 边缘节点缓存检查

边缘节点收到请求后,会检查缓存中是否已有该资源。这一步称为缓存命中检查

  • 缓存命中:如果边缘节点缓存中已经存在该资源,并且资源没有过期,则直接从缓存中读取并返回给用户。
  • 缓存未命中:如果缓存中没有该资源,或者资源已经过期,则会将请求转发给源服务器(origin server)。
5. 缓存命中或未命中
  • 缓存命中:如果资源已经存在并且有效,CDN会直接将缓存的资源返回给用户。这是加速访问的关键步骤,因为用户不需要访问源服务器,节省了时间和带宽。

    例如,若用户请求 https://www.example.com/images/logo.png,CDN的边缘节点可能已经缓存了这个文件,且TTL(过期时间)没有到期,此时CDN直接返回文件。

  • 缓存未命中:如果缓存中没有该资源,或者缓存的资源已经过期,CDN会向源服务器发起请求以获取资源。

6. 从源服务器获取资源

当缓存未命中时,CDN边缘节点会向原始服务器(origin server)请求该资源。此时,源服务器会根据请求返回最新的资源,并且将该资源缓存到边缘节点,以供下次请求使用。

  • 资源返回后,CDN会缓存到边缘节点并设置适当的缓存过期时间(TTL)。这意味着下一次请求时,边缘节点可以直接返回缓存的内容,而不需要再访问源服务器。
7. 返回资源给用户

无论是缓存命中还是从源服务器获取资源,最终,CDN的边缘节点会把响应数据返回给用户的浏览器。用户的浏览器从CDN边缘节点接收到资源,并进行展示。

8. 浏览器缓存

在资源返回给浏览器后,浏览器也会根据响应头(如 Cache-ControlExpires 等)进行本地缓存,以便在下一次访问时直接从本地缓存中获取资源,而不再发送请求到CDN或源服务器。

三、缓存策略与内容更新

CDN中的缓存策略非常关键,它决定了缓存内容的过期时间、更新方式以及缓存策略的灵活性。

  1. TTL(Time to Live,生存时间)
    • 每个缓存的资源都会设置一个TTL,TTL指定了该资源在CDN边缘节点缓存的有效期。TTL过期后,缓存的内容会被认为是过期的,需要重新向源服务器请求内容。
  2. 缓存清除
    • 主动清除:CDN提供商允许通过管理控制台或API来主动清除缓存中的某些资源。这对于资源更新频繁或紧急更新的情况非常重要。
    • 自动清除:当资源的TTL到期时,CDN会自动清除缓存并向源服务器请求新的内容。
  3. 缓存验证
    • 使用 ETagLast-Modified 等HTTP头部字段,CDN可以验证缓存是否有效。即使TTL未到期,CDN也可以通过向源服务器发送条件请求(If-None-MatchIf-Modified-Since)来判断缓存是否需要更新。

四、CDN的优势

  1. 减少延迟:用户总是能从离自己最近的边缘服务器获取资源,减少了传输延迟。
  2. 提高可用性:即使源服务器宕机,CDN仍可以从其他节点提供缓存的内容,保持服务可用。
  3. 减轻源服务器负担:通过缓存大量请求,CDN能够减轻源服务器的负载,减少带宽消耗。
  4. 提高网站性能:加速资源加载,提升用户体验,尤其是对于全球用户。

五、CDN请求流程示意图

 用户请求 --> DNS解析 --> CDN边缘节点 --> 缓存检查 -->
     |                          |                        |
  缓存命中                     缓存未命中                  |
     |                          |                        |
 返回缓存的资源             从源服务器请求资源            |
     |                          |                        |
返回给用户的资源             缓存资源并返回给用户        |

六、总结

  1. CDN工作流程:CDN通过将资源分发到多个边缘节点,利用智能路由、缓存和负载均衡技术,将资源快速交付给用户,减少延迟,提高网站性能。
  2. 缓存命中与未命中:CDN根据缓存策略决定是否直接返回缓存的内容,或者向源服务器请求更新内容。
  3. 浏览器与CDN缓存:浏览器本地缓存和CDN的缓存共同工作,确保资源加载更快,减少重复请求。

CDN在提高网站性能、增强网站可用性、降低带宽消耗等方面发挥了重要作用,是现代Web应用不可或缺的组成部分。

image-20241217113705693

1.4.2 CDN分层缓存

CDN(Content Delivery Network,内容分发网络)的分层缓存(Layered Caching)是指通过多级缓存架构有效提升内容分发效率的一种策略。在CDN中,请求的内容通常会经过多个层级的缓存节点,以实现更佳的性能和资源利用率。整个流程通常可以分为以下几个层次:

  1. L1 边缘节点缓存(Edge Cache)
    这是离用户最近的一层缓存节点。当用户向CDN请求内容时,边缘节点首先检查本地缓存是否已存有该内容。若存在并未过期,便直接从该节点返回内容给用户,降低传输延迟,提高用户体验;若缓存中无此内容或内容已过期,则向上层的缓存节点或源站请求。
  2. L2 区域或中间层缓存(Mid-Tier/Regional Cache)
    当边缘节点未能在本地拿到所需内容时,会将请求向上层的区域缓存节点发出。区域缓存通常位于更靠近源站的核心网络,储存那些在一定时间窗口内被多个边缘节点重复请求的内容。通过在此层进行缓存,CDN减少了向源站多次重复请求同一内容的频率。这一层有助于将热门内容在更广的地理范围内进行共享,降低源站负载,并减少跨区域的回源请求延迟。
  3. 源站(Origin Server)
    当所有中间层缓存与边缘缓存均无请求内容时,才会到达最终的源站。源站是内容的原始出处,CDN会从这里获取最新版本的内容,然后将其分发给请求用户,并在适当的层级缓存节点中储存副本,以便满足未来类似请求。

分层缓存的工作原理

以下是一个典型的用户请求过程:

  1. 用户访问网站,请求某个资源(例如一张图片)。
  2. 用户的DNS解析请求将用户导向离他最近的L1边缘节点。
  3. L1节点检查自身是否缓存了该资源。
    • 如果,则直接将资源返回给用户,请求结束。这称为“缓存命中”。
    • 如果没有,则L1节点向其上层的L2区域节点发起请求。
  4. L2节点执行相同的检查,查看自身是否缓存了该资源。
    • 如果,则将资源返回给L1节点,L1节点再将其返回给用户。同时,L1节点也会缓存该资源,以便下次相同的请求可以直接命中。
    • 如果没有,则L2节点继续向上,向源站发起请求。
  5. 源站将资源返回给L2节点,L2节点再返回给L1节点,L1节点最终返回给用户。L1和L2节点都会缓存该资源。

分层缓存的优势

  • 减轻源站压力: 通过多层缓存,大部分用户请求都可以在L1或L2节点得到满足,大大减少了回源站的请求数量,从而减轻了源站的负载。
  • 提高缓存命中率: 分层结构使得更常用的内容可以缓存在更靠近用户的L1节点上,从而提高整体的缓存命中率,减少用户访问延迟。
  • 降低网络拥塞: 由于大量请求在CDN内部完成,减少了跨区域和跨运营商的网络传输,有助于缓解网络拥塞。
  • 更好的可扩展性: 分层结构使得CDN系统更容易扩展,可以通过增加L1和L2节点来应对不断增长的用户访问量。

分片缓存(Chunked Caching)

在某些情况下,CDN还会使用分片缓存技术,将大文件(例如视频文件)分割成多个小片段(chunks),然后分别缓存这些片段。当用户请求文件时,CDN只需传输用户需要的片段,而不是整个文件。这对于提高大文件传输效率和支持流媒体播放非常有用。

总结

CDN分层缓存是一种有效的提高网站性能和用户体验的技术。通过合理地组织和管理多层缓存节点,CDN可以更好地分配资源,提高缓存命中率,并减轻源站的压力。

2.Redis 安装及连接

Redis简介
Redis(Remote Dictionary Server)是一个开源的内存数据结构存储系统,可以用作数据库、缓存和消息队列中间件。它以Key-Value形式存储数据,提供多种数据结构和丰富的功能特性。Redis的核心价值在于高速访问、简单的数据操作模型以及丰富的数据结构支持,使其在需要快速读写、实时计算和高并发的场景中表现突出。

Redis的主要特性

  1. 内存存储
    Redis将数据存储在内存中,从而达到非常高的访问速度(读写操作通常在微秒级别)。这使其在对实时性要求高的场景(如会话存储、实时排行、实时计数器等)表现优异。

  2. 多种数据结构支持
    相较于传统的Key-Value存储仅支持字符串,Redis支持多种丰富的数据结构类型,这些数据结构以简单命令即可操作:

    • String(字符串):最基础的数据结构,可存储普通字符串、数字、二进制数据。
    • Hash(哈希):类似于Key-Value映射的集合,可方便存储对象属性并对属性进行增删改操作。
    • List(列表):双端链表实现,支持从头尾插入、弹出元素,可用来实现消息队列、任务列表等功能。
    • Set(集合):无序集合结构,支持求交集、并集和差集等集合运算,常用于去重、标签管理。
    • Sorted Set(有序集合):每个元素会关联一个分数(score),Redis会根据分数对元素进行排序,可用于排行榜、延时队列等场景。
    • Bitmap(位图)、HyperLogLogGeo(地理位置)等特殊数据类型:满足统计计数、地理位置查询等特殊需求。
  3. 持久化能力
    虽然Redis是内存数据库,但它并非易失性存储。Redis提供两种持久化机制,让数据在断电后仍能恢复:

    • RDB(Redis Database Backup):定时生成内存快照并持久化到磁盘,恢复速度快,数据略有延迟。
    • AOF(Append Only File):将每次写操作以日志的形式追加到文件中,数据恢复更为完整,可根据策略对AOF文件进行定期重写压缩。

    可以根据业务需求选择合适的持久化方案,或同时开启RDB和AOF实现数据安全与高效率的折中。

  4. 高可用与分布式
    Redis提供主从复制(Master-Slave Replication)实现数据的多份冗余,主节点负责写操作,从节点同步主节点的数据,提供读取分流和故障切换。当主节点出现故障时,可手动或借助Redis Sentinel(哨兵)实现自动故障转移。
    对于更大规模的数据集与访问压力,Redis Cluster可以将数据分片至多个节点,提升整体存储能力和吞吐性能。

  5. 事务支持
    Redis提供简单的事务机制(MULTI/EXEC命令),可以将一组操作打包,保证这些操作的顺序性和原子性。虽然不支持复杂的回滚功能,但事务可以确保一组命令要么都执行要么都不执行。

  6. Lua脚本扩展
    Redis内置了Lua解释器,用户可以在Redis内原子执行Lua脚本,对数据进行复杂操作,而无需在客户端与Redis之间多次往返,提高复杂操作的性能和一致性。

  7. 丰富的使用场景
    凭借高性能和多数据结构支持,Redis可广泛应用于各种场景:

    • 缓存热点数据(例如:热门商品信息、用户会话数据、应用程序配置)
    • 消息队列与任务调度(利用List或Stream)
    • 实时统计(计数器、排行榜、实时分析)
    • 分布式锁(利用SetNx命令实现简单的分布式锁机制)
  8. 简单易用的命令行与客户端支持
    Redis提供简洁直观的命令行客户端和与主流编程语言(如Java、Python、Go、C#等)兼容的客户端库,降低学习成本与集成难度。


总结
Redis作为一个内存数据存储系统,具有高性能、丰富的数据类型、灵活的持久化策略以及高可用性架构支持。它在高并发、低延迟与实时处理场景中得到广泛应用,已成为构建现代互联网应用的重要基础组件。

image-20241218093552202

2.1 dnf 安装 Redis

# Rocky 9.4 由系统源提供
[root@redis1.xyy.org ~]#dnf info redis
Name         : redis
Version      : 6.2.7
Release      : 1.el9
Architecture : x86_64
Size         : 1.3 M
Source       : redis-6.2.7-1.el9.src.rpm
Repository   : appstream
Summary      : A persistent key-value database
URL          : https://redis.io
License      : BSD and MIT
Description  : Redis is an advanced key-value store. It is often referred to as a data
             : structure server since keys can contain strings, hashes, lists, sets and
             : sorted sets.
             :
             : You can run atomic operations on these types, like appending to a string;
             : incrementing the value in a hash; pushing to a list; computing set
             : intersection, union and difference; or getting the member with highest
             : ranking in a sorted set.
             :
             : In order to achieve its outstanding performance, Redis works with an
             : in-memory dataset. Depending on your use case, you can persist it either
             : by dumping the dataset to disk every once in a while, or by appending
             : each command to a log.
             :
             : Redis also supports trivial-to-setup master-slave replication, with very
             : fast non-blocking first synchronization, auto-reconnection on net split
             : and so forth.
             :
             : Other features include Transactions, Pub/Sub, Lua scripting, Keys with a
             : limited time-to-live, and configuration settings to make Redis behave like
             : a cache.
             :
             : You can use Redis from most programming languages also.

[root@Rocky9.4 ~]#

# CentOS 7由 epel 源提供
[root@CentOS7 ~]#yum info redis
Name        : redis
Arch        : x86_64
Version     : 3.2.12
Release     : 2.el7
Size        : 1.4 M
Repo        : installed
From repo   : epel
Summary     : A persistent key-value database
URL         : http://redis.io
License     : BSD

[root@redis1.xyy.org ~]#dnf install redis
[root@redis1.xyy.org ~]#systemctl enable --now redis
[root@redis1.xyy.org ~]#pstree -p | grep redis
           |-redis-server(4237)-+-{
   redis-server}(4238)
           |                    |-{
   redis-server}(4239)
           |                    |-{
   redis-server}(4240)
           |                    `-{
   redis-server}(4241)
[root@redis1.xyy.org ~]#
[root@redis1.xyy.org ~]#redis-cl
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> INFO Server
# Server
redis_version:6.2.7
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:ec192bdd77ecd321
redis_mode:standalone
os:Linux 5.14.0-427.13.1.el9_4.x86_64 x86_64
arch_bits:64
monotonic_clock:POSIX clock_gettime
multiplexing_api:epoll
atomicvar_api:c11-builtin
gcc_version:11.3.1
process_id:4237
process_supervised:systemd
run_id:37144e0c3a2930dac6148605d26afae8ee4d38ba
tcp_port:6379
server_time_usec:1734486571682241
uptime_in_seconds:37314
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:6433323
executable:/usr/bin/redis-server
config_file:/etc/redis/redis.conf
io_threads_active:0
127.0.0.1:6379>

2.2 编译安装 Redis

从 Redis 官方下载地址 获取稳定版压缩包,如 redis-7.4.0.tar.gz

image-20241218102907079
# 1.创建 Redis 用户(不需要登录权限,只是用于运行 Redis 服务以提高安全性)
useradd -r -s /sbin/nologin redis

# 2.获取源码包
wget https://download.redis.io/releases/redis-7.4.0.tar.gz

# 3.解压并进入源码目录
tar xf redis-7.4.0.tar.gz
cd redis-7.4.0

# 4.开始编译(在某些发行版下可开启 USE_SYSTEMD=yes 选项,以生成可与 systemd 交互的可执行文件。)
make -j $(nproc) USE_SYSTEMD=yes

# 5.安装到指定位置
make PREFIX=/apps/redis install

# 6.建立软链接(方便在命令行中使用redis-server、redis-cli)
ln -s /apps/redis/bin/redis-* /usr/bin/

# 7.创建所需目录
mkdir -p /apps/redis/{
   etc,log,data,run}

# 8.拷贝源码目录中自带redis.conf,拷贝到配置目录:
cp redis.conf /apps/redis/etc/

# 9.redis.conf:修改关键配置
#bind:改为 0.0.0.0 或保留默认看实际需要;
#requirepass:设置 Redis 密码,如 requirepass 123456;
#dir:RDB/快照文件存放目录,一般设为 /apps/redis/data;
#logfile:日志文件路径,如 /apps/redis/log/redis-6379.log;
#pidfile:pid 文件路径,如 /apps/redis/run/redis-6379.pid;
sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' \
       -e "/# requirepass/a requirepass 123456" \
       -e "/^dir .*/c dir /apps/redis/data/" \
       -e "/^logfile .*/c logfile /apps/redis/log/redis-6379.log" \
       -e "/^pidfile .*/c pidfile /apps/redis/run/redis-6379.pid" \
       /apps/redis/etc/redis.conf

# 10.设置文件权限
chown -R redis:redis /apps/redis

# 11.内核与系统参数优化(不优化会有告警)
	# 11.1 调整内核参数
vim /etc/sysctl.conf
net.core.somaxconn = 1024
vm.overcommit_memory = 1

sysctl -p

	# 11.2 禁用透明大页(THP)
echo never > /sys/kernel/mm/transparent_hugepage/enabled
# 可以写入启动脚本(如 /etc/rc.local 或 /etc/rc.d/rc.local)以在重启后继续生效。

# 12.创建Systemd服务并启动
# CentOS/Rocky:/usr/lib/systemd/system/redis.service
# Ubuntu:/lib/systemd/system/redis.service(或 /etc/systemd/system/redis.service)
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
# 启动notify一定要编译了 USE_SYSTEMD=yes,否则启动服务有问题
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

# 13.刷新并启动服务
systemctl daemon-reload
systemctl enable --now redis
systemctl status redis

# 14.查看Redis版本或者信息
redis-server -v
# 查看服务信息
redis-cli -a 123456 INFO Server
# 测试插入和查询数据
redis-cli -a 123456 set mykey "Hello World"
redis-cli -a 123456 get mykey

#! /bin/bash
#-----------------------------------------------------
#Author:            XingYuyu
#Date:              2024-08-12
#Blog:              http://8.141.4.74
#Filename:          install_redis.sh
#Description:       [Online Install Redis for Rocky Linux ,Ubuntu,CentOS ]
#-----------------------------------------------------
VERSION=redis-7.4.0
PASSWORD=123456
INSTALL_DIR=/apps/redis

os_type() {
   
  awk -F'[ "]' '/^NAME/{print $2}' /etc/os-release
}

color() {
   
  RES_COL=80
  MOVE_TO_COL="echo -en \e[${RES_COL}G"
  SETCOLOR_SUCCESS="echo -en \e[1;32m"
  SETCOLOR_FAILURE="echo -en \e[1;31m"
  SETCOLOR_WARNING="echo -en \e[1;33m"
  SETCOLOR_NORMAL="echo -en \e[0m"
  echo -n "$1" && $MOVE_TO_COL
  echo -n "["
  if [ $2 = "success" -o $2 = "0" ]; then
    ${SETCOLOR_SUCCESS}
    echo -n $"  OK  "
  elif [ $2 = "failure" -o $2 = "1" ]; then
    ${SETCOLOR_FAILURE}
    echo -n $"FAILED"
  else
    ${SETCOLOR_WARNING}
    echo -n $"WARNING"
  fi
  ${SETCOLOR_NORMAL}
  echo -n $"]"
  echo
}

install_redis() {
   
  wget https://download.redis.io/releases/${VERSION}.tar.gz || {
   
    color "Redis 源码下载失败" 1
    exit
  }
  tar xf ${VERSION}.tar.gz
  cd ${VERSION}
  CPUS=lscpu | awk '/^CPU\(s\)/{print $2}'
  make -j $CPUS USE_SYSTEMD=yes PREFIX=${INSTALL_DIR} install && color "Redis 编译安装完成" 0 || {
   
    color "Redis 编译安装失败" 1
    exit
  }
  ln -s ${INSTALL_DIR}/bin/redis-* /usr/bin/
  mkdir -p ${INSTALL_DIR}/{
   etc,log,data,run}
  cp redis.conf ${INSTALL_DIR}/etc/
  sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' -e "/# requirepass/a requirepass $PASSWORD" -e "/^dir .*/c dir ${INSTALL_DIR}/data/" -e "/^logfile .*/c logfile ${INSTALL_DIR}/log/redis-6379.log" -e "/^pidfile .*/c pidfile ${INSTALL_DIR}/run/redis-6379.pid" ${INSTALL_DIR}/etc/redis.conf
  if id redis &>/dev/null; then
    color "Redis 用户已经存在,无需创建" 0
  else
    useradd -r -s /sbin/nologin redis
    color "Redis 用户创建成功" 0
  fi
  chown -R redis.redis ${INSTALL_DIR}
  cat >>/etc/sysctl.conf <<EOF
net.core.somaxconn = 1024
vm.overcommit_memory = 1
EOF
  sysctl -p
  if [ `os_type` == "Ubuntu" ];then
      cat >> /lib/systemd/system/rc-local.service <<EOF
[Install]
WantedBy=multi-user.target
EOF
      echo '#!/bin/bash' > /etc/rc.local
      echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >>/etc/rc.local
      chmod +x /etc/rc.local
      /etc/rc.local
      # Ubuntu 的service文件放在/lib/systemd/system/下或者/etc/systemd/system/下不能放在/usr/lib/下
      cat > /lib/systemd/system/redis.service <<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=${INSTALL_DIR}/bin/redis-server ${INSTALL_DIR}/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT \$MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF
  else
      echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >>/etc/rc.d/rc.local
      chmod +x /etc/rc.d/rc.local
      /etc/rc.d/rc.local
      cat > /usr/lib/systemd/system/redis.service <<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=${INSTALL_DIR}/bin/redis-server ${INSTALL_DIR}/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT \$MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

EOF
  fi

  systemctl daemon-reload
  systemctl enable --now redis &>/dev/null
  systemctl is-active redis &> /dev/null && color "Redis 服务启动成功,Redis信息如下:" 3 || {
    color "Redis 启动失败" 1 ;exit; }
  #sleep 5
  redis-cli -a $PASSWORD INFO Server 2>/dev/null
}

install_CentOS7() {
   
  . /etc/init.d/functions
  # jemalloc-devel依赖于epel源
  yum -y install epel-release && yum -y install gcc jemalloc-devel systemd-devel || {
   
    color "安装软件包失败,请检查网络配置" 1
    exit
  }
  rpm -q wget &>/dev/null || yum -y install wget &>/dev/null
  wget https://download.redis.io/releases/${VERSION}.tar.gz || {
   
    action "Redis 源码下载失败" false
    exit
  }
  tar xf ${VERSION}.tar.gz
  cd ${VERSION}
  CPUS=lscpu | awk '/^CPU\(s\)/{print $2}'
  make -j $CPUS USE_SYSTEMD=yes PREFIX=${INSTALL_DIR} install && action "Redis 编译安装完成" || {
   
    action "Redis 编译安装失败" false
    exit
  }
  ln -s ${INSTALL_DIR}/bin/redis-* /usr/bin/
  mkdir -p ${INSTALL_DIR}/{
   etc,log,data,run}
  cp redis.conf ${INSTALL_DIR}/etc/
  sed -i -e 's/bind 127.0.0.1/bind 0.0.0.0/' -e "/# requirepass/a requirepass $PASSWORD" -e "/^dir .*/c dir ${INSTALL_DIR}/data/" -e "/^logfile .*/c logfile ${INSTALL_DIR}/log/redis-6379.log" -e "/^pidfile .*/c pidfile ${INSTALL_DIR}/run/redis-6379.pid" ${INSTALL_DIR}/etc/redis.conf
  if id redis &>/dev/null; then
    action "Redis 用户已经存在" false
  else
    useradd -r -s /sbin/nologin redis
  fi
  chown -R redis.redis ${INSTALL_DIR}
  cat >>/etc/sysctl.conf <<EOF
net.core.somaxconn = 1024
vm.overcommit_memory = 1
EOF
  sysctl -p
  echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >>/etc/rc.d/rc.local
  chmod +x /etc/rc.d/rc.local
  /etc/rc.d/rc.local

  cat >/usr/lib/systemd/system/redis.service <<EOF
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=${INSTALL_DIR}/bin/redis-server ${INSTALL_DIR}/etc/redis.conf --supervised systemd
ExecReload=/bin/kill -s HUP \$MAINPID
ExecStop=/bin/kill -s QUIT \$MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

EOF
  systemctl daemon-reload
  systemctl enable --now redis &>/dev/null
  systemctl is-active redis &> /dev/null && ${COLOR}"Redis 服务启动成功,Redis信息如下:"${END} || {
    ${COLOR}"Redis 启动失败"${END};exit; }
  #sleep 5
  redis-cli -a $PASSWORD INFO Server 2>/dev/null
}

install_Ubuntu() {
   
 apt -y install make gcc libjemalloc-dev libsystemd-dev || {
   
    color "安装软件包失败,请检查网络配置" 1
    exit
  }
  install_redis
}

install_Rocky() {
   
  # jemalloc-devel依赖于epel源
  yum -y install epel-release && yum -y install gcc jemalloc-devel systemd-devel || {
   
    color "安装软件包失败,请检查网络配置" 1
    exit
  }
  rpm -q wget &>/dev/null || yum -y install wget &>/dev/null
  install_redis
}

if [ $(os_type) == 'CentOS' ]; then
  install_CentOS7
elif [ $(os_type) == 'Rocky' ]; then
  install_Rocky
elif [ $(os_type) == 'Ubuntu' ]; then
  install_Ubuntu
else
  color "未识别的操作系统" 1
fi

2.3 连接到 Redis

2.3.1 客户端连接到 Redis

1.本机无密码连接

redis-cli

2.跨主机无密码连接

redis-cli -h HOSTNAME/IP -p PORT

3.跨主机密码连接

redis-cli -h HOSTNAME/IP -p PORT -a PASSWORD

2.3.2 程序连接 Redis

redis 支持多种开发语言访问

https://redis.io/docs/latest/develop/clients/

image-20241218152549416

shell 脚本写入数据到 Redis

#!/bin/bash

NUM=100
PASS=123456

for i in `seq $NUM`; do
    redis-cli -h 127.0.0.1 -a "$PASS" --no-auth-warning set key${i} value${i}
    echo "key${i} value${i} 写入完成"
done

echo "$NUM 个key写入到Redis完成"

3.Redis 的多实例

在生产环境中,为了更好地利用资源、实现多租户隔离或分离不同业务的数据与配置,运维人员往往会在一台服务器上运行多个 Redis 实例。Redis 的多实例部署并非Redis内建的特性,而是通过为每个实例指定独立的配置文件、独立的运行端口与数据目录来实现的。以下是关于Redis多实例的详细讲解:

为什么需要多实例

  1. 资源隔离与多租户支持
    在某些场景下,不同的业务线或不同的用户需要独立的Redis服务,以免数据和性能相互影响。多实例可以为每个业务运行独立的Redis,保证数据和访问流量的隔离。
  2. 不同的配置要求
    某些业务可能需要不同的持久化策略(RDB或AOF)、内存管理策略或安全设置。多实例部署允许针对每个实例使用单独的配置文件,从而灵活定制每个实例的行为。
  3. 更好地利用硬件资源
    一台物理机/虚拟机的CPU、内存、网络资源较为充裕时,可以在同一台机器上运行多个Redis实例,充分利用硬件资源。尤其在内存较大时,不同实例分别作为缓存、队列、会话存储使用,可以最大化硬件利用率。

配置多实例的关键点

  1. 独立的配置文件
    每个实例都需要一个独立的配置文件(例如 redis-6379.conf, redis-6380.conf)。
    在配置文件中需要注意如下参数:

    • port:每个实例必须使用不同的端口,如6379、6380、6381等。
    • pidfile:每个实例需要独立的PID文件,如 /var/run/redis_6379.pid/var/run/redis_6380.pid
    • logfile:为每个实例指定独立的日志文件,如 /var/log/redis_6379.log/var/log/redis_6380.log
    • dir:为每个实例指定独立的数据目录,如 /var/lib/redis/6379//var/lib/redis/6380/,确保RDB或AOF文件不冲突。
    • daemonize yes:通常在生产中,多实例都以守护进程方式后台运行。利用 systemd 的进程监督能力,即使用 --supervised systemd 参数时,必须将 daemonize 设为 no。如果将 daemonize 设为 yes,则与 systemd 的监督模式相矛盾,导致 Redis 无法正常通过 systemd 进行管理和监控。
  2. 独立的启动命令
    启动时为每个实例指定相应的配置文件。常用命令形式:

    redis-server /path/to/redis-6379.conf
    redis-server /path/to/redis-6380.conf
    

    确保每个实例正常监听自己的端口并使用自己的配置。

  3. 服务管理与守护进程
    为每个实例创建单独的systemd服务文件或init脚本,方便运维管理。如在systemd中创建 /etc/systemd/system/redis@6379.serviceredis@6380.service 等文件,然后通过 systemctl start redis@6379 启动指定实例。

  4. 安全与访问控制
    确保为每个实例设置合理的访问控制,如 bind参数、protected-mode设置、requirepass或ACL策略。多实例运行时应确保不同实例的数据和访问策略独立,避免安全隐患。

  5. 监控与报警
    多实例运行时需要对每个实例分别进行监控,收集其内存使用、连接数、QPS、延迟、慢查询等指标,并对异常情况及时报警。

举例:多实例文件组织形式

/etc/redis/
├─ redis-6379.conf
├─ redis-6380.conf
└─ redis-6381.conf

/var/lib/redis/
├─ 6379/
│  ├─ dump.rdb
│  └─ appendonly.aof
├─ 6380/
│  ├─ dump.rdb
│  └─ appendonly.aof
└─ 6381/
   ├─ dump.rdb
   └─ appendonly.aof

/var/log/
├─ redis_6379.log
├─ redis_6380.log
└─ redis_6381.log

总结

Redis多实例部署是通过为每个实例提供独立的端口、独立的配置文件以及数据和日志目录来实现的。这种方式在同一台服务器上实现了灵活的资源分配和多租户支持。通过精心配置和管理,运维人员能够同时运行多个Redis实例,为不同应用提供高效、独立而又经济实惠的内存数据存储服务。

案例:以编译安装为例实现 Redis 多实例

# 生成的文件列表
[root@Rocky9.4 ~]#ll /apps/redis/
total 0
drwxr-xr-x 2 redis redis 134 Dec 17 23:22 bin
drwxr-xr-x 2 redis redis  22 Dec 18 20:04 data
drwxr-xr-x 2 redis redis  24 Dec 18 20:04 etc
drwxr-xr-x 2 redis redis  28 Dec 17 23:22 log
drwxr-xr-x 2 redis redis  28 Dec 18 20:04 run

[root@Rocky9.4 redis]#tree /apps/redis/
/apps/redis/
├── bin
│   ├── redis-benchmark
│   ├── redis-check-aof -> redis-server
│   ├── redis-check-rdb -> redis-server
│   ├── redis-cli
│   ├── redis-sentinel -> redis-server
│   └── redis-server
├── data
│   ├── dump-6379.rdb
│   ├── dump-6380.rdb
│   └── dump-6381.rdb
├── etc
│   ├── redis_6379.conf
│   ├── redis_6380.conf
│   ├── redis_6381.conf
│   └── redis.conf
├── log
│   ├── redis-6379.log
│   ├── redis-6380.log
│   └── redis-6381.log
└── run
    ├── redis-6379.pid
    ├── redis-6380.pid
    └── redis-6381.pid

5 directories, 19 files



# 配置文件需要修改的地方
vim /apps/redis/etc/redis_6379.conf
bind 0.0.0.0 -::1
port 6379
daemonize no
pidfile /apps/redis/run/redis-6379.pid
logfile /apps/redis/log/redis-6379.log
# 写入数据的时候,并且满足save才会生产dump-6379.rdb这个文件
dbfilename dump-6379.rdb
dir /apps/redis/data/
# 3600秒,写一次数据 300秒,100次数据,60秒,10000次数据 满足就会备份,为了更快的看到效果可以更改,例如:save 60 1
save 3600 1 300 100 60 10000
appendfilename "appendonly-6379.aof"

vim /apps/redis/etc/redis_6380.conf
bind 0.0.0.0 -::1
port 6380
daemonize no
pidfile /apps/redis/run/redis-6380.pid
logfile /apps/redis/log/redis-6380.log
dbfilename dump-6380.rdb
dir /apps/redis/data/
save 3600 1 300 100 60 10000
appendfilename "appendonly-6380.aof"

vim /apps/redis/etc/redis_6381.conf
bind 0.0.0.0 -::1
port 6381
daemonize no
pidfile /apps/redis/run/redis-6381.pid
logfile /apps/redis/log/redis-6381.log
dbfilename dump-6381.rdb
dir /apps/redis/data/
save 3600 1 300 100 60 10000
appendfilename "appendonly-6381.aof"

# 创建service文件
# 1./usr/lib/systemd/system/redis6379.service
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis_6379.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

[root@Rocky9.4 ~]#

# 2./usr/lib/systemd/system/redis6380.service
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis_6380.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
#Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

[root@Rocky9.4 ~]#

# 3./usr/lib/systemd/system/redis6381.service
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=/apps/redis/bin/redis-server /apps/redis/etc/redis_6381.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
#Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
[root@Rocky9.4 ~]#


systemctl daemon-reload
systemctl enable --now redis6379.service redis6380.service redis6381.service
# 这里有个问题,通过二进制安装好的Redis,start的时候用tab键无法补全

4.Redis 持久化

Redis 是一个基于内存的数据结构存储系统,但它提供了多种持久化机制,可以将内存中的数据保存到磁盘中,从而在 Redis 重启或服务器宕机后依然能够恢复数据。Redis 主要提供了两种持久化方式:RDB(Redis Database)AOF(Append Only File)。这两种方式可以单独使用,也可以配合使用,具体选择取决于业务需求(对数据一致性、写入性能、磁盘空间等的不同要求)。

4.1 RDB(Redis Database)

RDB 方式是 Redis 最早的持久化模式,即在某个时间点对内存数据做快照,并保存到一个 .rdb 文件中

4.1.1 RDB 的工作机制

方法1:

SAVE 命令是“阻塞式”保存,Redis 不会创建子进程,而是直接由主进程把内存数据写到 RDB 文件里。

[root@Rocky9.4 redis]#( redis-cli -a 123456 save & );pstree -p | grep redis-server;ls /apps/redis/data/ -lh
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
           |-redis-server(28847)-+-{
   redis-server}(28854)
           |                     |-{
   redis-server}(28855)
           |                     |-{
   redis-server}(28856)
           |                     |-{
   redis-server}(28857)
           |                     `-{
   redis-server}(28858)
total 180M
-rw-r--r-- 1 redis redis 180M Dec 23 18:48 dump_6379.rdb
-rw-r--r-- 1 redis redis  48K Dec 23 21:45 temp-28847.rdb

使用 python 脚本存入一千万条数据,再进行备份看到下面的现象

# 这个需要使用pip install redis来安装redis包
import redis

pool=redis.ConnectionPool(host="10.0.0.41",port=6379,password="123456")
r=redis.Redis(connection_pool=pool)
for i in range(10000000):
    r.set("k%d" % i,"v%d" % i)
    data=r.get("k%d" % i)
    print(data)

image-20241223215647425

方法2:

BGSAVE 才是“后台”保存,Redis 会 fork 一个子进程来完成 RDB 持久化,主进程继续对外提供服务。

[root@Rocky9.4 data]#redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> bgsave
Background saving started
127.0.0.1:6379>

# 生产临时文件,fork 子进程 pid是920,从temp-920.rdb也可以看出是进程920在备份
[root@Rocky9.4 data]#pstree -p | grep redis-server;ls /apps/redis/data/ -lh
           |-redis-server(638)-+-redis-server(920)
           |                   |-{
   redis-server}(666)
           |                   |-{
   redis-server}(667)
           |                   |-{
   redis-server}(668)
           |                   |-{
   redis-server}(669)
           |                   `-{
    redis-server}(671)
total 128M
-rw-r--r-- 1 redis redis 67M Dec 24 14:43 temp-920.rdb
# 备份结束以后,将文件重命名
[root@Rocky9.4 data]#pstree -p | grep redis-server;ls /apps/redis/data/ -lh
           |-redis-server(638)-+-{
    redis-server}(666)
           |                   |-{
    redis-server}(667)
           |                   |-{
    redis-server}(668)
           |                   |-{
    redis-server}(669)
           |                   `-{
   redis-server}(671)
total 180M
-rw-r--r-- 1 redis redis 180M Dec 24 14:43 dump_6379.rdb

# 也可以查看日志
[root@Rocky9.4 data]#tail -f ../log/redis-6379.log
# bgsave的日志,会显示出具体的子进程编号
638:M 24 Dec 2024 15:15:14.746 * Background saving started by pid 1037
1037:C 24 Dec 2024 15:15:22.016 * DB saved on disk
1037:C 24 Dec 2024 15:15:22.026 * Fork CoW for RDB: current 0 MB, peak 0 MB, average 0 MB
638:M 24 Dec 2024 15:15:22.095 * Background saving terminated with success

# save的日志
638:M 24 Dec 2024 15:20:09.364 * DB saved on disk

image-20241224150259770

方法3:

Redis 会在配置文件中设置触发 RDB 生成快照

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/955469.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FPGA车牌识别

基于FPGA的车牌识别主要包含以下几个步骤&#xff1a;图像采集、颜色空间转换、边缘检测、形态学处理&#xff08;腐蚀和膨胀&#xff09;、特征值提取、模板匹配、结果显示。先用matlab对原理进行仿真&#xff0c;后用vivado和modelsim进行设计和仿真。 一、1.图像采集采用ov…

客户案例:致远OA与携程商旅集成方案

一、前言 本项目原型客户公司创建于1992年,主要生产并销售包括糖果系列、巧克力系列、烘焙系列、卤制品系列4大类,200多款产品。公司具有行业领先的生产能力,拥有各类生产线100条,年产能超过10万吨。同时,经过30年的发展,公司积累了完善的销售网络,核心经销商已经超过1200个,超…

怎么修复损坏的U盘?而且不用格式化的方式!

当你插入U盘时&#xff0c;若电脑弹出“需要格式化才能使用”提示&#xff0c;且无法打开或读取其中的数据&#xff0c;说明U盘极有可能已经损坏。除此之外&#xff0c;若电脑在连接U盘后显示以下信息&#xff0c;也可能意味着U盘出现问题&#xff0c;需要修复损坏的U盘&#x…

贪心算法(题1)区间选点

输出 2 #include <iostream> #include<algorithm>using namespace std;const int N 100010 ;int n; struct Range {int l,r;bool operator <(const Range &W)const{return r<W.r;} }range[N];int main() {scanf("%d",&n);for(int i0;i&l…

2.使用Spring BootSpring AI快速构建AI应用程序

Spring AI 是基于 Spring Boot3.x 框架构建&#xff0c;Spring Boot官方提供了非常便捷的工具Spring Initializr帮助开发者快速的搭建Spring Boot应用程序,IDEA也集成了此工具。本文使用的开发工具IDEASpring Boot 3.4Spring AI 1.0.0-SNAPSHOTMaven。 1.创建Spring Boot项目 …

【Linux】Socket编程-TCP构建自己的C++服务器

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; Socket 编程 TCP &#x1f98b; TCP socket API 详解&#x1f98b; 多线程远程命令执行&#x1f98b; 网络版计算器&#xff08;应用层自定义协议与序列化…

森林网络部署,工业4G路由器实现林区组网远程监控

在广袤无垠的林区&#xff0c;每一片树叶的摇曳、每一丝空气的流动&#xff0c;都关乎着生态的平衡与安宁。林区监控正以强大的力量&#xff0c;为这片绿色家园筑起一道坚固的防线。 工业 4G 路由器作为林区监控组网的守护者&#xff0c;凭借着卓越的通讯性能&#xff0c;突破…

数据库管理-第284期 奇怪的sys.user$授权(20250116)

数据库管理284期 20245-01-16 数据库管理-第284期 奇怪的sys.user$授权&#xff08;20250116&#xff09;1 问题2 CDB与PDB3 跨实例3.1 通过scanip访问数据库3.2 通过节点1的VIP访问数据库3.3 通过节点3的VIP访问数据库3.4 在节点3赋权后测试3.5 小结 总结 数据库管理-第284期 …

vue2配置跨域后请求的是本机

这个我来说明一下&#xff0c;因为我们公司的后端设置解决了跨域问题&#xff0c;所以我有很久没有看相关的内容了&#xff0c;然后昨天请求了需要跨域的接口&#xff0c;请求半天一直不对&#xff0c;浏览器显示的是本机地址&#xff0c;我以为是自己配置错了&#xff0c;后面…

从玩具到工业控制--51单片机的跨界传奇【3】

在科技的浩瀚宇宙中&#xff0c;51 单片机就像一颗独特的星辰&#xff0c;散发着神秘而迷人的光芒。对于无数电子爱好者而言&#xff0c;点亮 51 单片机上的第一颗 LED 灯&#xff0c;不仅仅是一次简单的操作&#xff0c;更像是开启了一扇通往新世界的大门。这小小的 LED 灯&am…

Java技术栈 —— 如何把项目部署到公网?

如何把项目部署到公网&#xff1f; 一、准备工作1.1 获得一台云服务器1.2 安装SSH客户端 二、云服务器部署2.1 配置云服务器2.2 使用nginx部署1个或多个前端项目 三、访问测试四、访问控制 平常大部分人都是本地写写项目&#xff0c;然后通过localhost的方式去访问&#xff0c;…

春秋杯-WEB

SSTI 可以看到主页那里有个登录测试之后为ssti {{4*4}} fenjing梭哈即可得到payload {{((g.pop.__globals__.__builtins__.__import__(os)).popen(cat flag)).read()}}file_copy 看到题目名字为file_copy&#xff0c; 当输入路径时会返回目标文件的大小&#xff0c; 通…

基于微信小程序教学辅助系统设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(六)

文章目录 一、考试管理模块实现1、添加考试功能实现1.1 页面设计1.2 前端功能实现1.3 后端功能实现1.4 效果展示2、考试管理功能实现2.1 页面设计2.2 前端功能实现2.3 后端功能实现2.3.1 后端查询接口实现2.3.2 后端编辑接口实现2.3.3 后端删除接口实现2.4 效果展示二、代码下载…

计算机网络 (43)万维网WWW

前言 万维网&#xff08;World Wide Web&#xff0c;WWW&#xff09;是Internet上集文本、声音、动画、视频等多种媒体信息于一身的信息服务系统。 一、基本概念与组成 定义&#xff1a;万维网是一个分布式、联机式的信息存储空间&#xff0c;通过超文本链接的方式将分散的信息…

如何学习数学 | 数学家如何思考

学习数学的关键在哪里&#xff1f; 原创 遇见数学 不少人面对数学都会觉得高深莫测&#xff0c;甚至非常枯燥乏味。 只有当你真正走入它的世界&#xff0c;才会发现里面蕴含着无尽的智慧和美感。要想推开这座数学的大门&#xff0c;需要的不仅仅是背公式&#xff0c;或者做一…

【Python通过UDP协议传输视频数据】(界面识别)

提示&#xff1a;界面识别项目 前言 随着网络通信技术的发展&#xff0c;视频数据的实时传输在各种场景中得到了广泛应用。UDP&#xff08;User Datagram Protocol&#xff09;作为一种无连接的协议&#xff0c;凭借其低延迟、高效率的特性&#xff0c;在实时性要求较高的视频…

ZNS SSD垃圾回收优化方案解读-2

四、Brick-ZNS 关键设计机制解析 Brick-ZNS 作为一种创新的 ZNS SSD 设计&#xff0c;聚焦于解决传统 ZNS SSDs 在垃圾回收&#xff08;GC&#xff09;过程中的数据迁移低效问题&#xff0c;其核心特色为存储内数据迁移与地址重映射功能。在应用场景中&#xff0c;针对如 Rock…

当PHP遇上区块链:一场奇妙的技术之旅

PHP 与区块链的邂逅 在技术的广袤宇宙中&#xff0c;区块链技术如同一颗耀眼的新星&#xff0c;以其去中心化、不可篡改、透明等特性&#xff0c;掀起了一场席卷全球的变革浪潮。众多开发者怀揣着对新技术的热忱与探索精神&#xff0c;纷纷投身于区块链开发的领域&#xff0c;试…

【原创】大数据治理入门(10)《数据资产化:从数据到价值》入门必看 高赞实用

数据资产化&#xff1a;从数据到价值 引言&#xff1a;数据资产化的概念 数据资产化&#xff08;Data Monetization&#xff09;是指将企业内部的各种数据转化为有价值的资产&#xff0c;通过数据的应用和分析提升企业的运营效率、降低成本、增加收入和优化决策。在大数据时代…