当前位置:科学 > 正文

分布式缓存

2023-01-23 13:49:12  来源:so贝塔

淘汰算法

最不经常使用算法(LFU)

这个缓存算法使用一个计数器来记录条目被访问的频率。通过使用LFU缓存算法,最低访问数的条目首先被移除。这个方法并不经常使用,因为它无法对一个拥有最初高访问率之后长时间没有被访问的条目缓存负责。

最近最少使用算法(LRU)

这个缓存算法将最近使用的条目存放到靠近缓存顶部的位置。当一个新条目被访问时,LRU将它放置到缓存的顶部。当缓存达到极限时,较早之前访问的条目将从缓存底部开始被移除。这里会使用到昂贵的算法,而且它需要记录“年龄位”来精确显示条目是何时被访问的。此外,当一个LRU缓存算法删除某个条目后,“年龄位”将随其他条目发生改变。

一个缓存被访问后,近期再被访问的可能性很大。可以记录每个缓存记录的最近访问时间,最近未被访问时间最长的数据会被首先淘汰。


(资料图片仅供参考)

优点:实现简单,能适应访问热点 缺点:对偶发的访问敏感,影响命中率 簿记开销:时间 O(1),空间 O(N)

自适应缓存替换算法(ARC)

再IBM Almaden研究中心开发,这个缓存算法同时跟踪记录LFU和LRU,以及驱逐缓存条目,来获得可用缓存的最佳使用。

先进先出算法(FIFO)

FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

越早进入缓存的数据,其不再被访问的可能性越大。因此在淘汰缓存时,应选择在内存中停留时间最长的缓存记录。使用队列即可实现该策略:

优点:实现简单,适合线性访问的场景 缺点:无法适应特定的访问热点,缓存的命中率差 簿记开销:时间 O(1),空间 O(N)

最近最常使用算法(MRU)

这个缓存算法最先移除最近最常使用的条目。一个MRU算法擅长处理一个条目越久,越容易被访问的情况。

更新策略

缓存更新的策略主要分为三种:

Cache Aside Pattern(旁路缓存)Read/Write Through Pattern(读写穿透)Write Behind Caching Pattern(异步写入)

缓存使用场景

分布式系统中要么通过2PC、3PC或Paxos协议保证强一致性,要么就是拼命的降低并发时脏数据的概率。缓存系统适用的场景就是非强一致性的场景,所以它属于CAP中的AP,只能做到BASE理论中说的最终一致性。异构数据库本来就没办法强一致,我们只是尽可能减少不一致的时间窗口,达到最终一致性。同时结合设置过期时间的兜底方案。

缓存场景分析

对于读多写少的数据,请使用缓存为了保持数据库和缓存的一致性,会导致系统吞吐量的下降为了保持数据库和缓存的一致性,会导致业务代码逻辑复杂缓存做不到绝对一致性,但可以做到最终一致性对于需要保证缓存数据库数据一致的情况,请尽量考虑对一致性到底有多高要求,选定合适的方案,避免过度设计

Cache Aside(旁路缓存)

Cache Aside(旁路缓存) 是最广泛使用的缓存模式之一,如果能正确使用 Cache Aside 的话,能极大的提升应用性能,Cache Aside可用来读或写操作。Cache Aside的提出是为了尽可能地解决缓存与数据库的数据不一致问题。

Read Cache Aside

Cache Aside 的读请求流程如下:

读的时候,先读缓存,缓存命中的话,直接返回数据缓存没有命中的话,就去读数据库,从数据库取出数据,放入缓存后,同时返回响应

Write Cache Aside

Cache Aside 的写请求流程如下:

更新的时候,先更新数据库,然后再删除缓存

Read/Write Through(读写穿透)

Read/Write Through(读写穿透) 模式中,服务端把缓存作为主要数据存储。应用程序跟数据库缓存交互,都是通过抽象缓存层完成的。

Read Through

Read Through 和 Cache Aside 很相似,不同点在于程序不需要再去管理从哪去读数据(缓存还是数据库)。相反它会直接从缓存中读数据,该场景下是缓存去决定从哪查询数据。当我们比较两者的时候这是一个优势因为它会让程序代码变得更简洁。Read Through的简要流程如下

从缓存读取数据,读到直接返回如果读取不到的话,从数据库加载,写入缓存后,再返回响应

该模式只在 Cache Aside 之上进行了一层封装,它会让程序代码变得更简洁,同时也减少数据源上的负载。流程如下:

Write Through

Write Through 模式下的所有写操作都经过缓存,每次向缓存中写数据时,缓存会把数据持久化到对应的数据库中去,且这两个操作都在一个事务中完成。因此,只有两次都写成功才是最终写成功。用写延迟保证了数据一致性。当发生写请求时,也是由缓存抽象层完成数据源和缓存数据的更新,流程如下:

向缓存中写数据,并向数据库写数据使用事务保证一致性,两者都写成功才成功

当使用 Write Through 的时候一般都配合使用 Read Through。Write Through 适用情况有:

需要频繁读取相同数据不能忍受数据丢失(相对 Write Behind 而言)和数据不一致

Write Through 的潜在使用例子是银行系统。

Write Behind(异步写入)

Write Behind(异步写入,又叫Write Back) 和 Read/Write Through 相似,都是由 Cache Provider 来负责缓存和数据库的读写。它们又有个很大的不同:Read/Write Through 是同步更新缓存和数据的,Write Behind 则是只更新缓存,不直接更新数据库,通过批量异步的方式来更新数据库。

这种方式下,缓存和数据库的一致性不强,对一致性要求高的系统要谨慎使用。但是它适合频繁写的场景,MySQL的InnoDB Buffer Pool 机制就使用到这种模式。如上图,应用程序更新两个数据,Cache Provider 会立即写入缓存中,但是隔一段时间才会批量写入数据库中。优缺点如下:

优点:是数据写入速度非常快,适用于频繁写的场景缺点:是缓存和数据库不是强一致性,对一致性要求高的系统慎用

数据一致性

一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的。

强一致性:这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往对系统的性能影响大弱一致性:这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态最终一致性:最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。这里之所以将最终一致性单独提出来,是因为它是弱一致性中非常推崇的一种一致性模型,也是业界在大型分布式系统的数据一致性上比较推崇的模型

业务延时双删

先删除缓存,再更新数据库中如何避免脏数据?采用延时双删策略。

先删除缓存再写数据库休眠1秒后再次删除缓存(这1秒=业务可能最大耗时,主要是等待正在加载脏数据的请求完成)

① 读写分离架构

读写架构中,先删除缓存,再更新数据库中如何避免脏数据?采用延时双删策略。

先淘汰缓存再写数据库休眠1秒后再次淘汰缓存(这1秒=主从同步可能最大耗时+业务可能最大耗时,主要是等待正在加载脏数据的请求完成)

② 延时双删导致吞吐量降低

延时双删的方式同步淘汰策略导致了吞吐量降低如何解决?

将第二次删除作为异步

MQ重试机制

不管是延时双删还是Cache-Aside的先操作数据库再删除缓存,都可能会存在第二步的删除缓存失败,导致的数据不一致问题,可以引入删除缓存重试机制来解决。

流程如下:

更新数据库数据删除缓存中的数据,可此时缓存服务出现不可用情况,造成无法删除缓存数据当删除缓存数据失败时,将需要删除缓存的 Key 发送到消息队列 (MQ) 中应用自己消费需要删除缓存 Key 的消息应用接收到消息后,删除缓存,如果删除缓存确认 MQ 消息被消费,如果删除缓存失败,则让消息重新入队列,进行多次尝试删除缓存操作

biglog异步删除

重试删除缓存机制会造成好多业务代码入侵。其实还可以这样优化:通过数据库的binlog来异步淘汰key。

流程如下:

更新数据库数据MySQL将数据更新日志写入binlog中Canal订阅&消费MySQL binlog,并提取出被更新数据的表名及ID调用应用删除缓存接口删除缓存数据Redis 不可用时,将更新数据的表名及 ID 发送到 MQ 中应用接收到消息后,删除缓存,如果删除缓存确认 MQ 消息被消费,如果删除缓存失败,则让消息重新入队列,进行多次尝试删除缓存操作,直到缓存删除成功为止

策略选择

删除or更新

操作缓存的时候,到底是删除缓存呢,还是更新缓存?日常开发中,我们一般使用的就是Cache-Aside模式。有些小伙伴可能会问, Cache-Aside在写入请求的时候,为什么是删除缓存而不是更新缓存呢?

我们在操作缓存的时候,到底应该删除缓存还是更新缓存呢?我们先来看个例子:

线程A先发起一个写操作,第一步先更新数据库线程B再发起一个写操作,第二步更新了数据库由于网络等原因,线程B先更新了缓存线程A更新缓存

这时候,缓存保存的是A的数据(老数据),数据库保存的是B的数据(新数据),数据不一致了,脏数据出现啦。如果是删除缓存取代更新缓存则不会出现这个脏数据问题。更新缓存相对于删除缓存,还有两点劣势:

如果你写入的缓存值,是经过复杂计算才得到的话。更新缓存频率高的话,就浪费性能啦在写数据库场景多,读数据场景少的情况下,数据很多时候还没被读取到,又被更新了,这也浪费了性能呢(实际上,写多的场景,用缓存也不是很划算的)

双写顺序

双写的情况下,先操作数据库还是先操作缓存?Cache-Aside 缓存模式中,有些小伙伴还是会有疑问,在写请求过来的时候,为什么是先操作数据库呢?为什么不先操作缓存呢?比如一条数据同时存在数据库、缓存,现在你要更新此数据,不管先更新数据库,还是先更新缓存,这两种方式都有问题。

方案一:先更新数据库,后更新缓存

如下案例会造成数据不一致。

A先把数据库更新为 123,由于网络问题,更新缓存的动作慢了。这时,B 去更新数据库了,改为了 456,紧接着把缓存也更新为456。现在A更新缓存的请求到了,把缓存更新为了 123。那么这时数据就不一致了,数据库里是最新的 456,而缓存是 123,是旧数据。因为数据库更新、缓存更新这2个动作不是原子的,在高并发操作时,这2个动作直接会插入其他动作。

方案二:先更新缓存,再更新数据库

如下案例也同样可能数据不一致。

缓存更新成功,数据为最新的,但数据库更新失败,回滚了,还是旧数据。还是非原子操作的原因。

注意:先操作数据库再操作缓存,不一样也会导致数据不一致嘛?它俩又不是原子性操作的。这个是会的,但是这种方式,一般因为删除缓存失败等原因,才会导致脏数据,这个概率就很低。接下来我们再来分析这种删除缓存失败的情况,如何保证一致性。

缓存更新

除了缓存服务器自带的缓存失效策略之外(Redis默认的有6中策略可供选择),还可以根据具体的业务需求进行自定义的缓存淘汰。常见的更新策略如下:

LRU/LFU/FIFO:都是属于当缓存不够用时采用的更新算法适合内存空间有限,数据长期不变动,基本不存在数据一不致性业务。比如一些一经确定就不允许变更的信息。超时剔除:给缓存数据设置一个过期时间适合于能够容忍一定时间内数据不一致性的业务,比如促销活动的描述文案。主动更新:如果数据源的数据有更新,则主动更新缓存对于数据的一致性要求很高,比如交易系统,优惠劵的总张数。

常见数据更新方式有两大类,其余基本都是这两类的变种:

方式一:先删缓存,再更新数据库

这种做法是遇到数据更新,我们先去删除缓存,然后再去更新DB,如左图。让我们来看一下整个操作的流程:

A请求需要更新数据,先删除对应的缓存,还未更新DBB请求来读取数据B请求看到缓存里没有,就去读取DB并将旧数据写入缓存(脏数据)A请求更新DB

可以看到B请求将脏数据写入了缓存,如果这是一个读多写少的数据,可能脏数据会存在比较长的时间(要么有后续更新,要么等待缓存过期),这是业务上不能接受的。

方式二:先更新数据库,再删除缓存

上图的右侧部分可以看到在A更新DB和删除缓存之间B请求会读取到老数据,因为此时A操作还没有完成,并且这种读到老数据的时间是非常短的,可以满足数据最终一致性要求。

删除缓存而非更新缓存原因

上图可以看到我们用的是删除缓存,而不是更新缓存,原因如下图:

上图我用操作代替了删除或更新,当我们做删除操作时,A先删还是B先删没有关系,因为后续读取请求都会从DB加载出最新数据;但是当我们对缓存做的是更新操作时,就会对A先更新缓存还是B先更新缓存敏感了,如果A后更新,那么缓存里就又存在脏数据了,所以 go-zero 只使用删除缓存的方式。

缓存更新请求处理流程

我们来一起看看完整的请求处理流程:

注意:不同颜色代表不同请求。

请求1更新DB请求2查询同一个数据,返回了老的数据,这个短时间内返回旧数据是可以接受的,满足最终一致性请求1删除缓存请求3再来请求时缓存里没有,就会查询数据库,并回写缓存再返回结果后续的请求就会直接读取缓存了

缓存问题

缓存雪崩

当大量缓存数据在同一时间过期(失效)或者 Redis 故障宕机时,如果此时有大量的用户请求,都无法在 Redis 中处理,于是全部请求都直接访问数据库,从而导致数据库的压力骤增,严重的会造成数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃,这就是缓存雪崩的问题。

发生缓存雪崩的原因及解决方案:

① 大量数据同时过期

均匀设置过期时间:给缓存数据的过期时间加上一个随机数互斥锁:加个互斥锁,保证同一时间内只有一个请求来构建缓存二级缓存:每一级缓存的失效时间都不同队列控制:使用MQ控制读取数据库的请求数据。即发N个消息,单线程消费热点数据缓存永远不过期物理不过期:针对热点key不设置过期时间逻辑过期:把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建

② Redis故障宕机

服务熔断或请求限流机制:启动服务熔断机制,暂停业务对缓存服务访问,直接返回错误;或启用限流机制构建Redis缓存高可靠集群:通过主从节点的方式构建Redis缓存高可靠集群开启Redis持久化机制:一旦重启,能直接从磁盘上自动加载数据恢复内存中的数据

缓存击穿

如果缓存中的某个热点数据过期了,此时大量的请求访问了该热点数据,就无法从缓存中读取,直接访问数据库,数据库很容易就被高并发的请求冲垮,这就是缓存击穿的问题,如秒杀活动。

缓存击穿跟缓存雪崩很相似,可以认为缓存击穿是缓存雪崩的一个子集。应对缓存击穿可以采取以下两种方案:

互斥锁方案:保证同一时间只有一个业务线程更新缓存,未能获取互斥锁的请求,要么等待锁释放后重新读取缓存,要么就返回空值或者默认值热点数据缓存永远不过期物理不过期:针对热点key不设置过期时间逻辑过期:把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建

缓存穿透

当用户访问的数据,既不在缓存中,也不在数据库中,导致请求在访问缓存时,发现缓存缺失,再去访问数据库时,发现数据库中也没有要访问的数据,没办法构建缓存数据来服务后续的请求。那么当有大量这样的请求到来时,数据库的压力骤增,这就是缓存穿透的问题。

缓存穿透的发生一般有这两种情况:

业务误操作:缓存中的数据和数据库中的数据都被误删除了,所以导致缓存和数据库中都没有数据黑客恶意攻击:故意大量访问某些读取不存在数据的业务

应对缓存穿透的方案,常见的方案有三种:

拦截非法请求布隆过滤器:构造一个BloomFilter过滤器,初始化全量数据,当接到请求时,在BloomFilter中判断这个key是否存在,如果不存在,直接返回即可,无需再查询缓存和DB缓存空对象:查存DB 时,如果数据不存在,预热一个特殊空值到缓存中。这样,后续查询都会命中缓存,但是要对特殊值,解析处理

布隆过滤器工作原理

布隆过滤器由「初始值都为 0 的位图数组」和「 N 个哈希函数」两部分组成。当我们在写入数据库数据时,在布隆过滤器里做个标记,这样下次查询数据是否在数据库时,只需要查询布隆过滤器,如果查询到数据没有被标记,说明不在数据库中。布隆过滤器会通过 3 个操作完成标记:

第一步:使用 N 个哈希函数分别对数据做哈希计算,得到 N 个哈希值第二步:将第一步得到的 N 个哈希值对位图数组的长度取模,得到每个哈希值在位图数组的对应位置第三步:将每个哈希值在位图数组的对应位置的值设置为 1

举个例子,假设有一个位图数组长度为 8,哈希函数 3 个的布隆过滤器:

Hot Key

产生原因

用户消费的数据远大于生产的数据(热卖商品、热点新闻、热点评论、明星直播)在日常工作生活中一些突发的的事件,例如:双十一期间某些热门商品的降价促销,当这其中的某一件商品被数万次点击浏览或者购买时,会形成一个较大的需求量,这种情况下就会造成热点问题。同理,被大量刊发、浏览的热点新闻、热点评论、明星直播等,这些典型的读多写少的场景也会产生热点问题。请求分片集中,超过单 Server 的性能极限在服务端读数据进行访问时,往往会对数据进行分片切分,此过程中会在某一主机 Server 上对相应的 Key 进行访问,当访问超过 Server 极限时,就会导致热点 Key 问题的产生。

问题危害

当某一热点 Key 的请求在某一主机上超过该主机网卡上限时,由于流量的过度集中,会导致服务器中其它服务无法进行。如果热点过于集中,热点 Key 的缓存过多,超过目前的缓存容量时,就会导致缓存分片服务被打垮现象的产生。当缓存服务崩溃后,此时再有请求产生,会缓存到后台 DB 上,由于DB 本身性能较弱,在面临大请求时很容易发生请求穿透现象,会进一步导致雪崩现象,严重影响设备的性能。

流量集中,达到物理网卡上限请求过多,缓存分片服务被打垮DB 击穿,引起业务雪崩

发现热key

预估热key,如秒杀商品,火爆新闻在客户端进行统计可用Proxy,如Codis可以在Proxy端收集利用redis自带命令,monitor,hotkeys。执行缓慢,不推荐使用利用流式计算引擎统计访问次数,如Storm、Spark Streaming、Flink

解决方案

通常的解决方案主要集中在对客户端和 Server 端进行相应的改造。

读写分离

架构中各节点的作用如下:

SLB 层做负载均衡Proxy 层做读写分离自动路由Master 负责写请求ReadOnly 节点负责读请求Slave 节点和 Master 节点做高可用

实际过程中 Client 将请求传到 SLB,SLB 又将其分发至多个 Proxy 内,通过 Proxy 对请求的识别,将其进行分类发送。例如,将同为 Write 的请求发送到 Master 模块内,而将 Read 的请求发送至 ReadOnly 模块。而模块中的只读节点可以进一步扩充,从而有效解决热点读的问题。读写分离同时具有可以灵活扩容读热点能力、可以存储大量热点Key、对客户端友好等优点。

热点数据

该方案通过主动发现热点并对其进行存储来解决热点 Key 的问题。首先 Client 也会访问 SLB,并且通过 SLB 将各种请求分发至 Proxy 中,Proxy 会按照基于路由的方式将请求转发至后端的 Redis 中。在热点 key 的解决上是采用在服务端增加缓存的方式进行。具体来说就是在 Proxy 上增加本地缓存,本地缓存采用 LRU 算法来缓存热点数据,后端 DB 节点增加热点数据计算模块来返回热点数据。Proxy 架构的主要有以下优点:

Proxy 本地缓存热点,读能力可水平扩展DB 节点定时计算热点数据集合DB 反馈 Proxy 热点数据对客户端完全透明,不需做任何兼容

热点key处理

热点数据的读取

在热点 Key 的处理上主要分为写入跟读取两种形式,在数据写入过程当 SLB 收到数据 K1 并将其通过某一个 Proxy 写入一个 Redis,完成数据的写入。假若经过后端热点模块计算发现 K1 成为热点 key 后, Proxy 会将该热点进行缓存,当下次客户端再进行访问K1时,可以不经Redis。最后由于Proxy是可以水平扩充的,因此可以任意增强热点数据的访问能力。

热点数据的发现

对于 db 上热点数据的发现,首先会在一个周期内对 Key 进行请求统计,在达到请求量级后会对热点 Key 进行热点定位,并将所有的热点 Key 放入一个小的 LRU 链表内,在通过 Proxy 请求进行访问时,若 Redis 发现待访点是一个热点,就会进入一个反馈阶段,同时对该数据进行标记。DB 计算热点时,主要运用的方法和优势有:

基于统计阀值的热点统计基于统计周期的热点统计基于版本号实现的无需重置初值统计方法DB 计算同时具有对性能影响极其微小、内存占用极其微小等优点

Big Key

Big Key指数据量大的key,由于其数据大小远大于其它key,导致经过分片之后,某个具体存储这个Big Key的实例内存使用量远大于其他实例,造成内存不足,拖累整个集群的使用。

常见场景

热门话题下的讨论大V的粉丝列表序列化后的图片没有及时处理的垃圾数据

大Key影响

大key会大量占用内存,在Redis集群中无法均衡Reids性能下降,影响主从复制在主动删除或过期删除时操作时间过长而引起服务阻塞

如何发现大Key

redis-cli --bigkeys命令。可以找到某个实例5种数据类型(String、hash、list、set、zset)的最大key。但如果Redis的key比较多,执行该命令会比较慢获取生产Redis的rdb文件,通过rdbtools分析rdb生成csv文件,再导入MySQL或其他数据库中进行分析统计,根据size_in_bytes统计bigkey

解决方案

优化big key的原则就是string减少字符串长度,而list、hash、set、zset等则减少成员数:

string类型的big key,尽量不要存入Redis中,可以使用文档型数据库MongoDB或缓存到CDN上。如果必须用Redis存储,最好单独存储,不要和其他的key一起存储设置一个阈值,当value的长度超过阈值时,对内容启动压缩,降低kv的大小评估大key所占的比例,由于很多框架采用池化技术,如:Memcache,可以预先分配大对象空间。真正业务请求时,直接拿来即用颗粒划分,将大key拆分为多个小key,独立维护,成本会降低不少大key要设置合理的过期时间,尽量不淘汰那些大key

其它问题

缓存预热

缓存预热是指系统上线后,提前将相关的缓存数据加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题,用户直接查询事先被预热的缓存数据。如果不进行预热,那么Redis初始状态数据为空,系统上线初期,对于高并发的流量,都会访问到数据库中, 对数据库造成流量的压力。

缓存预热思路

数据量不大的时候:工程启动的时候进行加载缓存动作数据量大的时候:设置一个定时任务脚本,进行缓存的刷新数据量太大的时候:优先保证热点数据进行提前加载到缓存

预热解决方案

直接写个缓存刷新页面,上线时手工操作下数据量不大,可以在项目启动的时候自动进行加载定时刷新缓存

缓存加载策略

使用时加载缓存。当需要使用缓存数据时,就从数据库中查出,第一次查出后,接下来的请求都能从缓存中查询到数据预加载缓存。在项目启动的时候,预加载类似“国家信息、货币信息、用户信息,新闻信息”等不是经常变更的数据

缓存降级

缓存降级是指当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。

降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。

分级降级预案:

一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警错误:比如可用率低于90%,或数据库连接池被打爆,或访问量突然猛增到系统能承受的最大阈值,此时可以根据情况自动降级或者人工降级严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级

关键词:

推荐阅读

iOS13正式版推送 iOS13正式版推送值得更新吗?

苹果发布iOS13 5,iOS和iPadOS13 5系统正式版发布,系统新增加了多项功能,用户在安装了正确的开发人员配置文件后可以从Apple开发人员中心 【详细】

虎门大桥怎么样了 虎门大桥没有问题可以恢复通车了吗?

关于虎门大桥已经连续几天成为热门话题了,5月5日,最开始为了保障安全,对交通实行双向封闭。5月10日,组织报告测评,而今天根据官方消息 【详细】

2025年取消燃油车 2025年取消燃油车是真的吗?

相信很多人都听说过中国2025年取消燃油车,接下来小编就带大家介绍一下相关知识,大家可以了解一下。汽车一般使用汽油、柴油等化石燃料作为 【详细】

未成年打赏可退还是真的吗?未成年打赏可退有什么法律依据?

今日,未成年打赏可退还的消息引发人们的热切讨论,未成年人网络打赏引发的纠纷,多年来成为人们关注的社会热点问题,那么未成年打赏可退还 【详细】

首都第二国际机场在哪里 首都第二国际机场为何选址大兴?

首都第二国际机场为何选址大兴?大兴位于北京的南部,为什么选在南边建设机场?现在北京机场有几个?为了确保首都的安全,南部修建了北京第二 【详细】

关于我们  |  联系方式  |  免责条款  |  招聘信息  |  广告服务  |  帮助中心

联系我们:85 572 98@qq.com备案号:粤ICP备18023326号-40

科技资讯网 版权所有