Tair 的缓存高级实践 | 学习笔记

简介: 快速学习 Tair 的缓存高级实践

开发者学堂课程【阿里云原生内存数据库 Tair 课程Tair 的缓存高级实践】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/1198/detail/18184


Tair 的缓存高级实践


内容介绍

通用的缓存技术

如何评估缓存

缓存运维

缓存问题排查


学习目标为:

一、理解互联网通用的共享缓存技术

二、从应用原理看对缓存系统的需求,和 Tair 在缓存上的场景增强

三、理解缓存的关键指标,了解 Tair 在其上的增强和应用

四、熟悉一般缓存的运维和 Tair 的可观测性

五、了解缓存的一些问题排查思路

图片26.png

请注意 Tair 在真正的使用中时能够服务于内存数据库和缓存两个场景,并且内存数据库的场景会越来越多,但是本次的分享聚焦在缓存上的业务系统和 Tair 怎样把系统做到做到极致。

 

一、介绍通用缓存技术

1、缓存读写&共享缓存

缓存主要的作用要给数据源降压,在本次分享中把数据源定义为数据库。因为数据库是可靠的存储,抗压能力相对较弱,如果大量的访问数据库,数据库的压力会较大,这会让整个的业务系统变慢,所以缓存就出现了。

图一是两种缓存中比较典型的一种缓存读写流程,较为简单,大家自行学习即可:

图片1.png

可以总结出在使用缓存时有以下两个特点:

(1)缓存是可以脏(dirty)的:

缓存在从数据库里把一份数据拷出来时,当我去更新数据库或是数据库内部发生变化时,缓存的变化需要一定的时间,这个时间就认为缓存脏(dirty)了。

(2)缓存是可以丢(miss)的:

缓存系统并不会把数据库中的所有内容或者数据元素的内容都给放进去,只能够缓存部分内容。如果这部分内容不需要,在删掉后再次访问时,在数据源里仍然会有,但是缓存里面是没有的。这时要重新去更新缓存,如果缓存丢掉了,那么数据也就没有了。

在正常的业务系统中,例如图一中介绍的缓存读写流程,这都是面向于一个应用,这时缓存可以相对灵活一点。可以直接在应用中开一块内存去做缓存。但当业务系统变大之后,一台业务机器已经不能够满足需求了,那么就要部署多台机器去做同一件事情。例如淘宝天猫的交易规模。当数万台,甚至十几万台机器同时去访问数据库或者是缓存时,如果还把缓存放在每个应用里边,当数据库更新,应用数据发生变化时,用户测的缓存无法相应更新,缓存系统就出现了问题。这种是自由缓存(Private Cache),贴近用户。但随着业务机器的变多,同步开销会越来越大,dirty 会越来越大,基本上不合用。之后互联网发展是共享缓存技术,它的设计原则是在数据库前面挡一会儿共享、通用的缓存,这就不用在每个业务测去做自己的自由缓存了,好处是更容易达到数据库和缓存的一致性,脏的时间会比较短,并且不需要同步些 app 不同的状态。因为读到的缓存的数据是一致的,这些业务里面的状态都是都是一致的。

图片2.png

共享缓存的特点是稳定性高,抗压性高。共享缓存虽然没有私有缓存那么靠近自己的业务,但是能解决缓存的一致性的问题。因为存的数据会比原来的大,所以成本会稍高。另外对于整体的共享缓存系统要求比较高,Memcache , dis , Tair 都可以做大规模共享缓存,它对于可靠性和可用性要求非常高。例如说业务系统有很多机器时,当批量重启时,瞬间的压力就会到缓存上而不是数据库上,这时缓存会自带默认的抗冲击,抗压力的能力。例如淘宝天猫在双十一那晚的最后一秒时压力最大,这时最大的压力就在 Tair 上,如果不能撑住压力,用户就很难去抢购了。

2共享缓存的场景

图片3.png

共享缓存离业务测越近越好。如果有一台机器时,在内存里面建缓存即可。但如果有很多台机器且在同一个地域部署的时候,做共享缓存即可。但是随着业务系统的变大。例如发展到全国或者全球的电商体系,或者是全球同服的游戏服务器,这样就会存在问题。因为不可以忽视网络传输对于缓存的影响。例如:做一个电商系统,在北京有很多台机器,在数据库前面挡了共享缓存就没有问题了。但是如果是在广州或是在深圳交易时,延迟会稍高一点,用户体感就会不好。这时一般会在深圳或者上海去部署一部分的业务机器。不过如果从上海去访问北京的缓存,或者是深圳去访问北京的缓存的效率依旧非常差。因为共享缓存离用业务越近越好,这时一般的做法是在上海和深圳搭建共享缓存,这样可以让缓存有效加快的运行效率。

图片4.png

在做共享缓存时,有多地域的引入,这些共享缓存就变成了每个区域的自由缓存,这就存在数据同步的问题。例如:北京的业务写了数据库,北京的数据库更新自己的缓存,上海和深圳的读到的数据是脏的。这里提供两个私有缓存的同步方案,第一是数据源的缓存,可以订阅更新:在阿里云上订阅数据库的变化,这样深圳或者是同步到上海的数据就会是一致的。但问题是还不够,因为缓存系统里面一部分数据是从数据库里拷贝加快运转的,但还有一部分数据是中间态的结构,这部分数据是不落数据库。所以第二个方案就是中间结果的缓存,可以多地写入:如果算一个中间值后想传到上海和深圳,这时候当业务系统去做完之后,就要写 MQ 让现在进去生产一部消息,让深圳和上海去消费掉消息,同理上海和深圳生产之后也要去北京来消费,所以说共享缓存同步的代价是非常高的。当业务变大之后,同步的开销会越来越大。这时一般就要求缓存能够做多活。

多活是一个很好的解决分离的方案。系统可以自动的把数据同步,这样就不需要MQ、DTS,这会极大的降低架构成本,这就是 Tair 为什么在做多活。这时电商体系发展到一定程度的一种必然的产物。

多活技术的技术核心是做在数据库内核里面的,多活的两个关键技术中是防回环和精确一次。防回环就是用户写入一条数据之后不能把改动的数据给同步回来。防回环第二个问题是缓存的很多命令,包括数据库也有很多命令并不是密等的操作。例如说买商品的话库存就要简易,如果库存发到远端去之后不知道成功或者失败,若是再试一次远端的话肯定就不对了。所以对于数据库内核最关键的两个问题是防回环和精确一次。

3、缓存技术的本质

缓存技术的本质是使用就近存储(locality)来提升查询性能的一种工程方法。

因为数据源比较远,可以是,数据源的一份或多份拷贝到缓存中:数据既然有多份,就会有一致性(consistency)的问题,这就是 dirty 的本质。

可以是,计算的中间结果:如果丢失,业务测需要保证重放(replay),大都需要幂等性(idempotence,必非充)接口,缓存是通用的方法,并非仅指通用缓存技术。

如果缓存丢失有以下情况及接解决方案:

访问不到即回源(sourcing),缓存系统恢复后即重建(rebuild);

衡量指标为:命中率(hit ratio)和源端压力(load of source);衡量命中率是因为缓存的本质就是给业务系统和数据源降压,如果命中率很差就意味着效率很差或访问人数少。第二是源端压力,缓存就是想给数据库降压,源端压力差效率也不高。

如果缓存脏,业务系统需要来做容错(fault tolerance)。缓存里也需要方法,缓存层要能够提供一致性容错方法如过期时间(TTL),锁(Optimistic/Pessimistic locking),一致性原语(ConsistencyPrimitives)。

4、缓存举例,Cache Aside

缓存技术无处不在。例如在写一段对话时,防止爆栈,防止中间结果重复计算等等;写动态规划开辟临时储存;CPU 里缓存是一个很重要的指标,大家如果有兴趣可以研究一下,CPU 里如果有多份拷贝的话就会有一致性的问题,大家可以研究一下相关协议;写程序时的寄存器等。但 Tair 提供的是大规模的种分布式的共享缓存技术。它的运行的模式叫做 Cache Aside 的模式。Cache Aside 的模式的特点是业务能够同时的访问缓存和数据源。业务测负责一致性问题,如果数据库出现问题,缓存也能继续工作,效率更高。业务负责 cache 的更新和生存周期管理。有一种不常见的情况:cache through 架构,这个不在本次介绍之内。

 

二、如何评估缓存

核心问题

1、成本

这是用户最关心的问题。不要狭义的定义成本,成本包括很多:时间成本,物料成本等等,但从技术上看如何评估物料成本。Cache 容量本质是命中率和存储量的折衷。缓存和命中率呈正相关的关系,而非线性关系,但如果数据的访问模型符合冷热效应时,即有些数据访问非常高,有些则非常低,这时仅需要很少的数据就能达到最佳折衷点,例如幂律分布理论最佳折衷点是N1/2;N是 key 数。但有些业务模型较复杂,不符合冷热效应,例如分析业务的分析型均匀分布,也不太具有时效性,这时很难做缓存,这样就需要较大的容量,成本就会上升。成本高本质上是大量无效和低质量数据被缓存和 Cache 的 Value 过大。内存存储永远是最贵的。

缓存也有方法。缓存最重要的是生存周期和淘汰策略。生存周期就是为每一个数据设置生存周期(Expiration,TTL),到一定时间就自动删除,这是缓存系统和KV系统最大的区别,Time-to-Live 对缓存非常重要,一般都会在核心实现每对象的属性,区别于 KV 系统,没有 TTL 设置的 KV 系统不适合做缓存使用。第二部分是淘汰,淘汰就是用很小的数据量,用满就直接淘汰数据,因为淘汰是随机的,这会使错误成本和运维成本非常高,建议设置,但尽量不要用,如果要用的话成本会非常高。

图片5.png

2、命中率

第一个问题是命中率只代表运行效率,和系统是否有问题没有必然关系。但要求要能够知道,数据源无 cache 抗压能力是多少,要预留部分容量/性能安全裕量(Margin)和水位,不要用完,保持安全水位,否则缓存忙的时候,影响较大。

第二个要小心缓存的惊群效应。例如图八:

图片6.png

图八是一个分布式缓存,有四个区域,如果一个出现了问题,即空切,这时重新拉起一个实例时是没有数据的,命中率从百分之百降低到了百分之七十五,数据库的的压力变大。等待一段时间缓存重建后才会重新恢复百分之百,这说明缓存的拉起速度非常重要,越快越好。要尽量防止 cache 一次性全丢失:缓存的 HA 策略是单副本空切。缓存一旦全部丢掉,这时缓存的压力全部都到数据源上了,业务系统就很容易崩掉。还要避免数据批量失效(cache stampede),上节课有介绍,冲击数据,压测数据合理清理,需要对 TTL 做适当 mush-up。 所以很重要的能力是抗冲击性。例如有一百台机器,批量重启大量机器,会有大量冲击,读数据等,如果扛不住就会有问题。

Tair 在缓存核心问题能力的增强(相较于社区版 Redies)

抗压和抗冲击能力,3x性能;

高精度探活:10s内切换(相较于社区30-60s)。缓存在拉起虽然越快越好,但如果太快容易误切,一般在10s为好,Redies 可能长达几分钟,这就很危险。

如果说就是有弱点的话,Proxy 可开启更高抗压能力的 Query Cache。

3、一致性

图片7.png

Tc:当源数据库变成只读,或不写数据时,业务系统自然就会更新缓存,这时缓存时间如果和数据库时间一致。Tc 约等于0时,数据库必须要强一致,Tc 越小,缓存性能越差,维护代价越大,Tc 越大,dirty 可能性越大,容错性就要越强。缓存不能是无限发散的,这毫无意义。

Cache 需要有一致性增强的语义,这在某些场景下是有必要的。

图片8.png


悲观等待(不建议用):lock,如subscribe,brpop 等,

乐观更新有:CAS,version string等(TairString),

缓存和 DB 的强一致,外部协调器等,如 GTS,事务中间件等,这种缓存代价较高,也不建议使用。

4Tair 在一致性能力上的增

下面是 Tair 在一致性能力上的增强。之所以使用乐观模型,这是因为乐观模型性能很好地帮助用户解决并发问题,做悲观锁的话代价太高,没有查询一次缓存快。

图11,ky 做缓存时加了TTL,如果带乐观锁的话,需要加一个 version。有了它之后就相当于只做一个版本的概念,可以更好的管理数据。这里不多讲,后面会有介绍。

乐观锁在 Redis 社区版代价太高:非每对象属性;TairString 携带 Version;

TairHash 携带Version和field(子key)的 TTL;更多的原语(CAS/CAD),语法(exCAS)。

图片9.png

跳出一致性的前提是使用内存数据库取代缓存+数据源。缓存存在一致性原因是由于数据有多份拷贝,如果跳出一致性,Tair 具有缓存和数据库,直接用内存数据库来替代缓存+数据源。Tair 优先保证数据可靠性和可用性,modules(TairStack)和半同步适合内存数据库场景。


三、缓存运维

1缓存类型和数据选型

缓存选型和数据选型宜分布式共享缓存。缓存要离客户的实例应用尽量近,不要跨region,不要跨 az;尽量分布式分片多的实例做大规模缓存,前面的空切可以看去分片越多越好;关键链路主备副本会在有较好的体感:如 Session;如果 key space能区分,尽量采用不同的实例隔离(而非通过select),缓存和KV存储一定要分开,一旦混入,K数据无法清除,数据将无法使用;区分内存数据库场景(不能设置TTL和清空的,不要和缓存实例公用);缓存和缓存之间也要分开,例如冷热效应,缓存和kv存储的一定要分开,数据无法清除,就无法再使用。

数据选择要选择相对静止的数据作为副本 cache 会有有效提升读命中;对高度变化的数据做中间态cache会有效提升写入性能;优先缓存 meta 状态,而非 data 数据;状态作用很大,可降低开销。

2缓存的可观测性和 Tair 的增强

最后是缓存的可观测性和 Tair 的增强。缓存是“测不准”的。 缓存很难观测,因为缓存没有日志,且缓存的观测资源消耗远大于缓存访问本身,问题大都无法精确还原。在线可观测性有事件(Event:如慢查询)和监控(Metrics),离线可观测性有日志(logging),内容分析(introspection),历史事件,缓存分析,时延洞察(latency microscope),慢速和诊断调试有审计,聚合分析(Proxy),未来上线有内存视图,Eventbus,同样 porting back 回所有的阿里云 redis 数据库中。

最后是前馈和反馈,如果等到反馈就比较晚了。缓存的前馈多是依照经验,有一定难度,但前馈(feedforward)比反馈(feedback)更有效。

3缓存安全

对于安全是关注较少的,安全不仅仅有容灾等等。缓存安全还包括:

数据的可靠性和可用性:副本、容灾、备份/恢复,PITR(Tai);

访问安全:账号,密码,安全组。审计;

链路安全(SSL/TLS),和落盘安全(Tair TDE);

系统安全:防破解,限流,Airbag(Tair),沙箱(Tair);

缓存会有强制动,在使用时建议:

IP白名单和区分账号密码保持最小原则;

尽量不要触发引擎的强制动:如限流,会导致所有业务受损。

合理备份数据:救急/事后分析;

高敏感数据尽量选用链路/落盘加密;图片10.png


四、缓存问题的排查

1缓存内容不符合预期

如果缓存内容不符合预期有以下问题定位:

如数据无丢失,基本判定是业务问题,

丢失场景:Eviction,不正确的超时/删除,可在监控中观察输出,

事后复原:默认无 access log,查阅监控,结合应用侧分析,这远比在缓存重要容易,这是有损的,建议在低速和调试时使用。

历史记录:备份数据和恢复

图片11.png

使用建议如下:

低速/debug 模式可开启审计来尝试复原

使用version string(TairString或者TairHash)来避免竞争

缓存的各种可观测并不能完全替代业务测 Tracing,业务测要做好埋点。

图片12.png

2 Head-of-Line 阻塞导致缓存大规模不可用
现象:一个分片受影响,从而影响全局分布式缓存。一个节点宕机,不能迅速拉起,proxy 会分发命令,到db2的请求被挂起,堆积在队列,耗尽 proxy 内部资源导致整个 proxy 不可用,发生 HOL blocking。

原理:在 Tair 集群版 Proxy 上发生 HOL blocking

原理:在用户侧发生 HOL blocking
节点的拉起/切换速度是缓存系统的核心指标之一。

图片13.png

使用建议:

数据模型设置为点查;

慎用 scatter-gather-merge:批量获取要按 slot 区分;

处理部分过期:业务回源,缓存如果丢了,或找不到建议回源。

3、服务抖动

缓存工作在同步链路,抖动直接影响体感,抖动的排查是全链条体系排查,具体有哪些问题可看图19。

图片14.png

进行排查时有一些定式,例如:数据库系统提供的rt是P99/95/50 latency,熵的数据有部分提高是正常的,缓存系统的抖动等都会导致这个问题。最终要以业务影响为最核心指标来考虑。

排查方法有:
Top-down/Bottom-up:从上往下看是看业务系统有没有问题,从下往上看是看缓存系统有没有问题。评估是从下往上还是从下往上的根据是一台有问题,还是全部有问题。

缓存的基础排查:从下往上查时要优先看缓存的资源使用情况,如网络限流等。

同地域多个实例(包含其他服务)受影响一般是查不出来的,要关注网络通告最有难度的是小规模 max-rt 抖动排查:优先抓包,先排除业务测。

相关文章
|
3月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
Java本地高性能缓存实践问题之SpringBoot中引入Caffeine作为缓存库的问题如何解决
|
3月前
|
缓存 Java Spring
Java本地高性能缓存实践问题之Caffeine中设置刷新机制的问题如何解决
Java本地高性能缓存实践问题之Caffeine中设置刷新机制的问题如何解决
|
3月前
|
存储 缓存 Java
Java本地高性能缓存实践问题之如何定义Caffeine的缓存
Java本地高性能缓存实践问题之如何定义Caffeine的缓存
|
3月前
|
缓存 Java
Java本地高性能缓存实践问题之Caffeine缓存库中基于时间设置驱逐策略的问题如何解决
Java本地高性能缓存实践问题之Caffeine缓存库中基于时间设置驱逐策略的问题如何解决
|
3月前
|
缓存 Java
Java本地高性能缓存实践问题之AsyncCache中移除一个缓存元素的问题如何解决
Java本地高性能缓存实践问题之AsyncCache中移除一个缓存元素的问题如何解决
|
3月前
|
缓存 Java
Java本地高性能缓存实践问题之使用Caffeine的Cache接口来查找一个缓存元素的问题如何解决
Java本地高性能缓存实践问题之使用Caffeine的Cache接口来查找一个缓存元素的问题如何解决
|
6天前
|
存储 缓存 NoSQL
保持HTTP会话状态:缓存策略与实践
保持HTTP会话状态:缓存策略与实践
|
27天前
|
存储 缓存 NoSQL
深入理解后端缓存机制的重要性与实践
本文将探讨在后端开发中缓存机制的应用及其重要性。缓存,作为提高系统性能和用户体验的关键技术,对于后端开发来说至关重要。通过减少数据库访问次数和缩短响应时间,缓存可以显著提升应用程序的性能。本文将从缓存的基本概念入手,介绍常见的缓存策略和实现方式,并通过实例展示如何在后端开发中有效应用缓存技术。最后,我们将讨论缓存带来的一些挑战及其解决方案,帮助您在实际项目中更好地利用缓存机制。
|
30天前
|
存储 缓存 监控
HTTP:强缓存优化实践
HTTP强缓存是提升网站性能的关键技术之一。通过精心设计缓存策略,不仅可以显著减少网络延迟,还能降低服务器负载,提升用户体验。实施上述最佳实践,结合持续的监控与调整,能够确保缓存机制高效且稳定地服务于网站性能优化目标。
43 3
|
3月前
|
缓存 Java Maven
Java本地高性能缓存实践问题之缓存中获取用户信息的问题如何解决
Java本地高性能缓存实践问题之缓存中获取用户信息的问题如何解决

热门文章

最新文章