图解大型网站多级缓存的分层架构

news2024/10/7 7:32:36

前言

缓存技术存在于应用场景的方方面面。从浏览器请求,到反向代理服务器,从进程内缓存到分布式缓存,其中缓存策略算法也是层出不穷。

假设一个网站,需要提高性能,缓存可以放在浏览器,可以放在反向代理服务器,还可以放在应用程序进程内,同时可以放在分布式缓存系统中。

从用户请求数据到数据返回,数据经过了浏览器,CDN,代理服务器,应用服务器,以及数据库各个环节。每个环节都可以运用缓存技术。

从浏览器/客户端开始请求数据,通过 HTTP 配合 CDN 获取数据的变更情况,到达代理服务器(Nginx)可以通过反向代理获取静态资源。

再往下来到应用服务器可以通过进程内(堆内)缓存,分布式缓存等递进的方式获取数据。如果以上所有缓存都没有命中数据,才会回源到数据库。

缓存的请求顺序是:用户请求 → HTTP 缓存 → CDN 缓存 → 代理服务器缓存 → 进程内缓存 → 分布式缓存 → 数据库。

看来在技术的架构每个环节都可以加入缓存,看看每个环节是如何应用缓存技术的。

image.png

HTTP 缓存

当用户通过浏览器请求服务器的时候,会发起 HTTP 请求,如果对每次 HTTP 请求进行缓存,那么可以减少应用服务器的压力。

当第一次请求的时候,浏览器本地缓存库没有缓存数据,会从服务器取数据,并且放到浏览器的缓存库中,下次再进行请求的时候会根据缓存的策略来读取本地或者服务的信息。

私有缓存

私有缓存是绑定到特定客户端的缓存——通常是浏览器缓存。由于存储的响应不与其他客户端共享,因此私有缓存可以存储该用户的个性化响应。该种缓存

如果响应包含个性化内容并且你只想将响应存储在私有缓存中,则必须指定 private 指令。

Cache-Control: private

image.png

共享缓存

共享缓存位于客户端和服务器之间,可以存储能在用户之间共享的响应,可以供多个客户端使用的缓存,通常依赖于代理服务器。

客户端发起的第一个请求通过代理服务器访问源服务器,缓存生效后会存放在代理服务器,后续客户端发起的相同请求,均由代理服务器提供缓存服务,共享缓存可以减轻源服务器的压力

image.png

其实共享代理可以细分为代理缓存托管缓存,简单理解代理缓存由代理服务器管理,位于客户端与原始服务器之间,减轻服务器负载、提高响应速度。托管缓存由内容提供商或 CDN 管理,分布全球,提供更快的内容传递和更好的用户体验。

缓存处理机制

下方为整体处理机制示意图,后文很多内容针对图中某些环节进行扩展讲解

image.png

上面强缓存中的 Pragma 大多数用于 http 1.0(http 1.1 中也适用),而 Cache-Control 只能应用于 http 1.1

需要注意的是,Expires 为服务端返回的过期时间,这种判断缓存是否过期的方式在  HTTP 1.0 用的比较多,到了 HTTP 1.1 会使用 Cache-Control 的 max-age 属性替代(单位是秒)

Last-Modified/If-Modified-Since 规则

在客户端第一次请求的时候,服务器会返回资源最后的修改时间,记作 Last-Modified。客户端将这个字段连同资源缓存起来。

当客户端再次请求服务器时,会把 Last-Modified 连同请求的资源一起发给服务器,这时 Last-Modified 会被命名为 If-Modified-Since,但其内容一样。

服务器收到请求,会把 If-Modified-Since 字段与服务器上保存的 Last-Modified 字段作比较:

  • 若服务器上的 Last-Modified 最后修改时间大于请求的 If-Modified-Since,说明资源被改动过,就会把资源(包括 Header+Body)重新返回给浏览器,同时返回状态码 200
  • 若资源的最后修改时间小于或等于 If-Modified-Since,说明资源没有改动过,只会返回 Header,并且返回状态码 304。浏览器接受到这个消息就可以使用本地缓存库的数据。

注意,Last-Modified 和 If-Modified-Since 指的是同一个值,只是在客户端和服务器端的叫法不同。

ETag / If-None-Match 规则

客户端第一次请求的时候,服务器会给每个资源生成一个 ETag 标记。这个 ETag 是根据每个资源生成的唯一 Hash 串,资源如何发生变化 ETag 随之更改,之后将这个 ETag 返回给客户端,客户端把请求的资源和 ETag 都缓存到本地。

在浏览器第二次请求服务器相同资源时,会把资源对应的 ETag 一并发送给服务器。在请求时 ETag 会被命名为 If-None-Match,但其内容不变

服务器收到请求后,会把 If-None-Match 与服务器上资源的 ETag 进行比较:

  • 如果不一致,说明资源被改动过,则返回资源(Header+Body),返回状态码 200。
  • 如果一致,说明资源没有被改过,则返回 Header,返回状态码 304。浏览器接受到这个消息就可以使用本地缓存库的数据。
规则使用时机

那么什么时候使用修改日期(Last-Modified)再验证和实体标签再验证(ETag)呢?

  • 如果服务器返回了一个 ETag 首部,客户端就必须使用 If-None-Match 实体标签再验证;
  • 如果服务器返回了一个 Last-Modified 首部,客户端就可以使用 If-Modified-Since 修改日期再验证;
  • 如果 ETag 和 Last-Modified 都提供了,客户端就应该同时使用这两种再验证方案。

如果HTTP/1.1缓存或服务器收到的请求既带有 If-Modified-Since,又带有 If-None-Match,那么只有这两个条件都满足时,才能返回304 Not Modified响应。

缓存控制策略

对于网站来说,缓存是达到高性能的重要组成部分,缓存需要合理配置,因为并不是所有资源都是永久不变的。Cache-Control 首部可以对缓存进行控制,Cache-Control 能用于 HTTP 请求和响应中,支持多个指令,以逗号分隔:

请求首部描述
Cache-Control: no-store不使用缓存。
Cache-Control: no-cache使用缓存前,无论本地副本是否过期,都需要请求源服务器进行验证(协商缓存验证)。
Cache-Control: max-age=秒设置缓存存储的最大期限,超过这个期限缓存被认为过期,时间是相对于请求的时间。
Cache-Control: max-stale=秒客户端愿意接收一个已经过期的资源。可以设置一个可选的秒数,表示响应不能已经过时超过该给定的时间。
Cache-Control: min-fresh=秒客户端希望获取一个能在指定的秒数内保持其最新状态的响应。
响应首部描述
Cache-Control: no-store不使用缓存。
Cache-Control: no-cache使用缓存前,无论本地副本是否过期,都需要请求源服务器进行验证(协商缓存验证)。
Cache-Control: max-age=秒设置缓存存储的最大期限,超过这个期限缓存被认为过期,时间是相对于请求的时间。
Cache-Control: s-maxage=秒同 max-age,仅适用于共享缓存。
Cache-Control: private私有缓存,响应只能被单个客户端缓存。
Cache-Control: public共享缓存,即由缓存代理服务器提供的缓存,响应可以被多个客户端缓存。
Cache-Control: must-revalidate如果本地副本未过期,则可继续供客户端使用,不需要向源服务器再验证;如果本地副本已过期(比如已经超过 max-age),在成功向源服务器验证之前,缓存不能用该资源响应后续请求。
Cache-Control: proxy-revalidate同 must-revalidate,仅适用于共享缓存。

Cache-Control有几个指令特别容易混淆,不能望文生义。比如no-cache,并不是指不能用 cache,客户端仍会把带有 no-cache 的响应缓存下来,只不过每次不会直接用缓存,而是要先去服务端验证一下。如果你想让客户端完全不缓存响应,应该用no-store,带有no-store的响应不会被缓存到任意的磁盘或者内存里,它才是真正的 no-cache

下面是对三个容易混淆的指令进行对比说明:

首部描述
Cache-Control: no-store不使用缓存。
Cache-Control: no-cache无论本地副本是否过期,都需要请求源服务器进行验证。
Cache-Control: must-revalidate如果本地副本未过期,可以使用本地副本;否则,需要请求源服务器进行验证。

CDN 缓存

HTTP 缓存主要是对静态数据进行缓存,把从服务器拿到的数据缓存到客户端/浏览器。

如果在客户端和服务器之间再加上一层 CDN,可以让 CDN 为应用服务器提供缓存,如果在 CDN 上缓存,就不用再请求应用服务器了。并且 HTTP 缓存提到的两种策略同样可以在 CDN 服务器执行。

CDN 的全称是 Content Delivery Network,即内容分发网络。其目的是通过在现有的 Internet 中增加一层新的网络架构,将网站的内容发布到最接近用户的网络"边缘",使用户可以就近取得所需的内容,解决 Internet 网络拥塞状况,提高用户访问网站的响应速度。

从技术上全面解决由于网络带宽小、用户访问量大、网点分布不均等原因所造成的用户访问网站响应速度慢的问题。

CDN 分发系统架构

image.png

CDN 工作流程

image.png

用户访问某个站点的内容时,若该站点使用了 CDN 网络,则在用户会在域名解析时获得 CDN 网络 GSLB 设备的 IP 地址。GSLB 设备根据其预设的选择策略(如,地理区域、用户时间等)为用户选择最合适的内容缓存节点,并且使用某种方式(如,基于 DNS、基于 HTTP 重定向、基于 IP 欺骗的方式等)导引用户访问所选的内容缓存节点。

用户继续向缓存节点发出请求,若缓存中包含请求的内容,则直接返回给用户,否则从核心Web服务器中获取该内容,缓存后返回给用户。这样当用户再次访问相同内容或其他用户访问相同内容时,可以直接从缓存中读取,提高了效率。

负载均衡缓存

说完客户端(HTTP)缓存和 CDN 缓存,我们离应用服务越来越近了,在到达应用服务之前,请求还要经过负载均衡器。

虽说它的主要工作是对应用服务器进行负载均衡,但是它也可以作缓存。可以把一些修改频率不高的数据缓存在这里,例如:用户信息,配置信息。通过服务定期刷新这个缓存就行了。

以 Nginx 为例,我们看看它是如何工作的:

  • 用户请求在达到应用服务器之前,会先访问 Nginx 负载均衡器,如果发现有缓存信息,直接返回给用户。
  • 如果没有发现缓存信息,Nginx 回源到应用服务器获取信息。
  • 另外,有一个缓存更新服务,定期把应用服务器中相对稳定的信息更新到 Nginx 本地缓存中。

image.png

进程内缓存

通过了客户端,CDN,负载均衡器,我们终于来到了应用服务器。应用服务器上部署着一个个应用,这些应用以进程的方式运行着,那么在进程中的缓存是怎样的呢?

进程内缓存又叫托管堆缓存,以 Java 为例,这部分缓存放在 JVM 的托管堆上面,同时会受到托管堆回收算法的影响。

由于其运行在内存中,对数据的响应速度很快,通常我们会把热点数据放在这里。

在进程内缓存没有命中的时候,我们会去搜索进程外的缓存或者分布式缓存。这种缓存的好处是没有序列化和反序列化,是最快的缓存。缺点是缓存的空间不能太大,对垃圾回收器的性能有影响。

目前比较流行的实现有 Ehcache、GuavaCache、Caffeine。这些架构可以很方便的把一些热点数据放到进程内的缓存中。

这里我们需要关注几个缓存的回收策略,具体的实现架构的回收策略会有所不同,但大致的思路都是一致的:

  • FIFO(First In First Out):先进先出算法,最先放入缓存的数据最先被移除。
  • LRU(Least Recently Used):最近最少使用算法,把最久没有使用过的数据移除缓存。
  • LFU(Least Frequently Used):最不常用算法,在一段时间内使用频率最小的数据被移除缓存。

在分布式架构的今天,多应用中如果采用进程内缓存会存在数据一致性的问题。

解决方案

保障进程内缓存数据一致性,有以下几种方案

单节点通知修改方案

image.png

第一种方案,可以通过单节点通知其他节点。如上图:写请求发生在 server1,在修改完自己内存数据与数据库中的数据之后,可以主动通知其他 server 节点,也修改内存的数据。

这种方案的缺点是:同一功能的一个集群的多个节点,相互耦合在一起,特别是节点较多时,网状连接关系极其复杂。

消息队列修改方案

image.png

第二种方案,可以通过 MQ 通知其他节点。如上图,写请求发生在 server1,在修改完自己内存数据与数据库中的数据之后,给 MQ 发布数据变化通知,其他 server 节点订阅 MQ 消息,也修改内存数据。

这种方案虽然解除了节点之间的耦合,但引入了MQ,使得系统更加复杂。

前两种方案,节点数量越多,数据冗余份数越多,数据同时更新的原子性越难保证,一致性也就越难保证。

Timer 修改方案

image.png

第三种方案,为了避免耦合,降低复杂性,干脆放弃了“实时一致性”,每个节点启动一个timer,定时从后端拉取最新的数据,更新内存缓存。在有节点更新后端数据,而其他节点通过timer更新数据之间,会读到脏数据。

应用场景

为什么不能频繁使用进程内缓存?

分层架构设计,有一条准则:站点层、服务层要做到无数据无状态,这样才能任意的加节点水平扩展,数据和状态尽量存储到后端的数据存储服务,例如数据库服务或者缓存服务。

可以看到,站点与服务的进程内缓存,实际上违背了分层架构设计的无状态准则,故一般不推荐使用。

那么什么情况下可以考虑使用进程内缓存?

情况一,只读数据,可以考虑在进程启动时加载到内存。

其实此时也可以把数据加载到 redis / memcache,进程外缓存服务也能解决这类问题。

情况二,极高并发,如果透传后端压力极大的场景,可以考虑使用进程内缓存。

例如,秒杀业务,并发量极高,需要站点层挡住流量,可以使用内存缓存。

情况三,一定程度上允许数据不一致业务

例如,有一些计数场景,运营场景,页面对数据一致性要求较低,可以考虑使用进程内页面缓存。

再次强调下,进程内缓存的适用场景并不如 redis/memcache 广泛,不要为了炫技而使用。

分布式缓存

与进程内缓存相对应的就是进程外缓存,它拥有更大的缓存容量,并且可以部署到不同的物理节点,通常会用分布式缓存的方式实现。

分布式缓存是与应用分离的缓存服务,最大的特点是,自身是一个独立的应用/服务,与本地应用隔离,多个应用可直接共享一个或者多个缓存应用/服务。

image.png

既然是分布式缓存,缓存的数据会分布到不同的缓存节点上,每个缓存节点缓存的数据大小通常也是有限制的。

数据被缓存到不同的节点,为了能方便的访问这些节点,需要引入缓存代理,类似 Twemproxy。他会帮助请求找到对应的缓存节点。

同时如果缓存节点增加了,这个代理也会只能识别并且把新的缓存数据分片到新的节点,做横向的扩展。

为了提高缓存的可用性,会在原有的缓存节点上加入 Master/Slave 的设计。当缓存数据写入 Master 节点的时候,会同时同步一份到 Slave 节点。

一旦 Master 节点失效,可以通过代理直接切换到 Slave 节点,这时 Slave 节点就变成了 Master 节点,保证缓存的正常工作。

每个缓存节点还会提供缓存过期的机制,并且会把缓存内容定期以快照的方式保存到文件上,方便缓存崩溃之后启动预热加载。

当缓存做成分布式的时候,数据会根据一定的规律分配到每个缓存应用/服务上,需要缓存的数据量比较大就需要扩展多个缓存节点来实现,这么多的缓存节点,客户端的请求不知道访问哪个节点怎么办?缓存的数据又如何放到这些节点上?

下面介绍三种缓存数据分片的算法,有了这些算法缓存代理就可以方便的找到分片的数据

哈希分片

image.png

Hash 分片的算法就是对缓存的 Key 做哈希计算,然后对总的缓存节点个数取余。你可以这么理解:

比如说,我们部署了三个缓存节点组成一个缓存的集群,当有新的数据要写入时,我们先对这个缓存的 Key 做比如 crc32Hash 算法生成 Hash 值,然后对 Hash 值模 3,得出的结果就是要存入缓存节点的序号。

这个算法最大的优点就是简单易理解,缺点是当增加或者减少缓存节点时,缓存总的节点个数变化造成计算出来的节点发生变化,从而造成缓存失效不可用。

所以如果采用这种方法,最好建立在你对于这组缓存命中率下降不敏感,比如下面还有另外一层缓存来兜底的情况下。那有没有更好的方案能解决这个问题呢?那就是一致性 Hash 分片算法。

一致性哈希分片

用一致性 Hash 算法可以很好地解决增加和删减节点时,命中率下降的问题。在这个算法中,我们将整个 Hash 值空间组织成一个虚拟的圆环,然后将缓存节点的 IP 地址或者主机名做 Hash 取值后,放置在这个圆环上。当我们需要确定某一个 Key 需要存取到哪个节点上的时候,先对这个 Key 做同样的 Hash 取值,确定在环上的位置,然后按照顺时针方向在环上“行走”,遇到的第一个缓存节点就是要访问的节点。比方说下面这张图里面,Key 1Key 2 会落入到 Node 1 中,Key 3Key 4 会落入到 Node 2 中,Key 5 落入到 Node 3 中,Key 6 落入到 Node 4 中。

image.png

这时如果在 Node 1Node 2 之间增加一个 Node 5,你可以看到原本命中 Node 2Key 3 现在命中到 Node 5,而其它的 Key 都没有变化;同样的道理,如果我们把 Node 3 从集群中移除,那么只会影响到 Key 5 。所以你看,在增加和删除节点时,只有少量的 Key漂移 到其它节点上,而大部分的 Key 命中的节点还是会保持不变,从而可以保证命中率不会大幅下降。

image.png

不过,事物总有两面性。虽然这个算法对命中率的影响比较小,但它还是存在问题:

  • 缓存节点在圆环上分布不平均,会造成部分缓存节点的压力较大;
  • 当某个节点故障时,这个节点所要承担的所有访问都会被顺移到另一个节点上,会对后面这个节点造成压力。

一致性哈希的脏数据问题

极端情况下,比如一个有三个节点 A、B、C 承担整体的访问,每个节点的访问量平均,A 故障后,B 将承担双倍的压力(A 和 B 的全部请求),当 B 承担不了流量 Crash 后,C 也将因为要承担原先三倍的流量而 Crash,这就造成了整体缓存系统的雪崩。

解决方案就是在一致性 Hash 算法中引入虚拟节点的概念,它将一个缓存节点计算多个 Hash 值分散到圆环的不同位置,这样既实现了数据的平均,而且当某一个节点故障或者退出的时候,它原先承担的 Key 将以更加平均的方式分配到其他节点上,从而避免雪崩的发生。

其次,就是一致性 Hash 算法的脏数据问题。为什么会产生脏数据呢? 比方说,在集群中有两个节点 AB,客户端初始写入一个 Key 为 k,值为 3 的缓存数据到 Cache A 中。这时如果要更新 k 的值为 4,但是缓存 A 恰好和客户端连接出现了问题,那这次写入请求会写入到 Cache B 中。接下来缓存 A 和客户端的连接恢复,当客户端要获取 k 的值时,就会获取到存在 Cache A 中的脏数据 3,而不是 Cache B 中的 4

所以,在使用一致性 Hash 算法时一定要设置缓存的过期时间,这样当发生漂移时,之前存储的脏数据可能已经过期,就可以减少存在脏数据的几率。

image.png

很显然,数据分片最大的优势就是缓解缓存节点的存储和访问压力,但同时它也让缓存的使用更加复杂。在 MultiGet(批量获取)场景下,单个节点的访问量并没有减少,同时节点数太多会造成缓存访问的 SLA(即“服务等级协议”,SLA 代表了网站服务可用性)得不到很好的保证,因为根据木桶原则,SLA 取决于最慢、最坏的节点的情况,节点数过多也会增加出问题的概率,因此我推荐 46 个节点为佳。

按照数据范围分片

常见场景就是按照 时间区间ID区间 来切分。例如:按日期将不同月甚至是日的数据分散到不同的库中;将 userId1~9999 的记录分到第一个库, 10000~20000 的分到第二个库,以此类推。某种意义上,某些系统中使用的 “冷热数据分离” ,将一些使用较少的历史数据迁移到其他库中,业务功能上只提供热点数据的查询,也是类似的实践。

这样的优点在于:

  • 单表大小可控
  • 天然便于水平扩展,后期如果想对整个分片集群扩容时,只需要添加节点即可,无需对其他分片的数据进行迁移
  • 使用分片字段进行范围查找时,连续分片可快速定位分片进行快速查询,有效避免跨分片查询的问题。

缺点:

  • 热点数据成为性能瓶颈。连续分片可能存在数据热点,例如按时间字段分片,有些分片存储最近时间段内的数据,可能会被频繁的读写,而有些分片存储的历史数据,则很少被查询

参考链接

  • 一篇文章让你明白你多级缓存的分层架构 - 掘金 (juejin.cn)
  • 分布式多级缓存SDK设计的思考-腾讯云开发者社区-腾讯云 (tencent.com)
  • 多级缓存架构设计 - 秦羽的思考 - 博客园 (cnblogs.com)
  • HTTP 缓存 - HTTP | MDN (mozilla.org)
  • 30分钟搞懂 HTTP 缓存 - 掘金 (juejin.cn)
  • 【CDN 最佳实践】CDN缓存策略解读和配置策略 - 知乎 (zhihu.com)
  • CDN图解(秒懂 + 史上最全) - 疯狂创客圈 - 博客园 (cnblogs.com)
  • 009.Nginx缓存配置 - 木二 - 博客园
  • 进程内缓存,究竟怎么玩?-阿里云开发者社区 (aliyun.com)
  • Hash分片,一致性Hash分片和按照数据范围分片三种常用的数据分片方式-腾讯云开发者社区-腾讯云 (tencent.com)

本文由博客一文多发平台 OpenWrite 发布!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4月6号排序算法(2)

堆排序 讲堆排序之前我们需要了解几个定义 什么叫做最大堆,父亲节点,以及孩子节点 将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。 每个节点都是它的子树的根节点的父亲 。 反过来每个节点都是它父亲的孩子 。 …

post请求搜索功能爬虫

<!--爬虫仅支持1.8版本的jdk--> <!-- 爬虫需要的依赖--> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.2</version> </dependency>…

「 典型安全漏洞系列 」11.身份验证漏洞详解

身份验证是验证用户或客户端身份的过程。网站可能会暴露给任何连接到互联网的人。这使得健壮的身份验证机制成为有效的网络安全不可或缺的一部分。 1. 什么是身份验证 身份验证即认证&#xff0c;是验证给定用户或客户端身份的过程。身份验证漏洞使攻击者能够访问敏感数据和功…

网络安全之命令注入

漏洞原理&#xff1a; 应用系统设计需要给用户提供指定的远程命令操作的接口&#xff0c;比如&#xff1a;路由器&#xff0c;防火墙&#xff0c;入侵检测等设备的web管理界面。一般会给用户提供一个ping操作的web界面 用户从web界面输入目标IP&#xff0c;提交后台会对改IP地…

C语言 练习题

目录 1.统计二进制中1的个数 方法1 方法2 方法3 2.求两个数二进制中不同位的个数 方法1 方法2 3.打印整数二进制的奇数位和偶数位 4.用“ * ”组成的X形图案 5.根据年份和月份判断天数 6.结语 1.统计二进制中1的个数 【题目内容】 写一个函数返回参数二进制中 1 的个…

MATLAB实现数值求解高阶常微分方程组

一、高阶常微分方程组 高阶常微分方程是指包含多个高阶常微分方程的系统。这些方程通常涉及多个未知函数及其高阶导数。解决高阶常微分方程组通常比解决单个高阶常微分方程更为复杂&#xff0c;因为需要同时考虑多个方程和多个未知函数之间的关系。 一般来说&#xff0c;解决…

数据库 06-03 时间戳

01.什么是时间戳 “时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。通俗的讲, 时间戳是一份能够表示一份数据在一个特定时间点已经存在的完整的可验证的数据。 02.用时间戳实现调度 定义 数据库给予一个事务一个时…

安全的通信协议HTTPS被攻击改采用什么防护方案

随着互联网的发展&#xff0c;保护用户在网上交换的敏感信息的安全性变得至关重要。HTTPS&#xff08;Hypertext Transfer Protocol Secure&#xff09;作为一种安全的通信协议&#xff0c;通过加密数据传输&#xff0c;保护用户的隐私和数据安全。然而&#xff0c;尽管HTTPS提…

具有温度系数(Temperature)的Softmax函数

Softmax 函数 softmax 函数是一种激活函数&#xff0c;通常用作神经网络最后一层的输出函数。该函数是两个以上变量的逻辑函数的推广。 Softmax 将实数向量作为输入&#xff0c;并将其归一化为概率分布。 softmax函数的输出是与输入具有相同维度的向量&#xff0c;每个元素的…

openharmony launcher 调研笔记(02)UI 调用逻辑

最近在看launcher&#xff0c;把自己调研的点做个笔记&#xff0c;持续修改更新中&#xff0c;个人笔记酌情参考。 EntryView Column() { PageDesktopLayout(); } .height(this.workSpaceHeight) // this.mWorkSpaceHeight this.mScreenHe…

使用GPT需要注意的事项

GPT出来之后&#xff0c;基本就告别浏览器搜索问题答案了。将问题原封不动的copy给GPT基本可以得到解答。 但是这个也有弊端&#xff0c;那就是太依赖GPT了。 1&#xff0c;使用GPT需要更强的专业知识&#xff1a;除了能问对问题&#xff0c;还要具备识别GPT&q…

Tomcat管理配置

Tomcat管理配置 1 host-manager项目2 manager项目 Tomcat 提供了Web版的管理控制台&#xff0c;位于webapps目录下。Tomcat 提供了用于管理Host的host-manager和用于管理Web应用的manager。 1 host-manager项目 Tomcat启动之后&#xff0c;可以通过 http://localhost:8080/ho…

【51单片机入门记录】RTC(实时时钟)-DS1302概述

目录 一、基于三线通信的RTC-DS1302 &#xff08;1&#xff09;简介 &#xff08;2&#xff09;特性 &#xff08;3&#xff09;引脚介绍 &#xff08;4&#xff09;控制字的格式 &#xff08;5.0&#xff09;日历时钟寄存器介绍 &#xff08;5.1&#xff09;日历时钟寄存…

阿里巴巴拍立淘API新功能揭秘:图片秒搜商品,实现智能化个性化购物新体验

在数字化快速发展的今天&#xff0c;智能化和个性化已经成为购物体验中不可或缺的元素。为了满足消费者日益增长的购物需求&#xff0c;阿里巴巴中国站不断推陈出新&#xff0c;其中拍立淘API的新功能——图片秒搜商品&#xff0c;无疑为智能化个性化购物体验开创了新的篇章。 …

数据挖掘入门项目二手交易车价格预测之建模调参

文章目录 目标步骤1. 调整数据类型&#xff0c;减少数据在内存中占用的空间2. 使用线性回归来简单建模3. 五折交叉验证4. 模拟真实业务情况5. 绘制学习率曲线与验证曲线6. 嵌入式特征选择6. 非线性模型7. 模型调参&#xff08;1&#xff09; 贪心调参&#xff08;2&#xff09;…

IDEA/PyCharm/GoLand同时打开2个分支

背景 想对比2个分支的代码&#xff0c;或者在A分支开发时&#xff0c;需要看B分支&#xff0c;切来切去太麻烦&#xff0c;而且新写的代码还没法直接切到B分支。 操作方法 假如有A、B 2个分支。 通过git worktree为B分支新建1个worktree&#xff0c;然后通过打开新项目的方式…

谷歌在生成式人工智能领域的挑战与机遇:内部纷争与市场压力下的战略调整

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

第12届蓝桥杯省赛 ---- C/C++ C组

文章目录 1. ASC2. 空间3. 卡片4. 相乘5. 路径6.时间显示7.最少砝码8. 杨辉三角形9. 左孩子右兄弟 第12届蓝桥杯省赛&#xff0c;C/C C组真题&#xff0c;第10题不是很清楚&#xff0c;题解不敢乱放&#x1f601;&#x1f601;&#x1f601; 1. ASC 额。。。。 #include <i…

【数据库】SQL简介

SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;是一种用于管理关系型数据库管理系统&#xff08;RDBMS&#xff09;的标准化语言。它用于访问和操作数据库中的数据&#xff0c;执行各种任务&#xff0c;如插入、更新、删除和检索数据&#x…

为何一个网卡需要配置多个IP地址?

在Linux环境中&#xff0c;一个网卡配置多个IP地址是一个常见且强大的网络管理策略&#x1f6e0;️。这种策略不仅增加了网络的灵活性和效率&#xff0c;还能满足特定的网络需求和应用场景&#x1f3af;。让我们一探究竟&#xff0c;看看在哪些情况下&#xff0c;为什么一个网卡…