当前位置: 首页 > 科技观察

阿里P8架构师谈:分布式缓存应用场景、选型对比、问题与挑战

时间:2023-03-22 01:13:54 科技观察

为什么要使用分布式缓存在高并发环境下,比如典型的淘宝双11秒杀,数亿用户几分钟内涌入淘宝,如果此时不阻塞访问,就会有大量的读写请求流向数据库。由于磁盘和内存的处理速度明显不在一个数量级,所以服务器马上就宕机了。从减轻数据库压力和提高系统响应速度两个角度出发,会在数据库前面加一层缓存。如果访问压力较大,CDN会在缓存前开始拦截图片等访问请求。并且由于最早的单机内存资源和承载能力有限,如果大量使用本地缓存,相同的数据会被不同的节点存储多份,造成内存资源的大量浪费。分布式缓存。分布式缓存应用场景Pagecache。用于缓存网页的内容片段,包括HTML、CSS和图片等;应用程序对象缓存。缓存系统作为ORM框架的二级缓存对外提供服务。目的是减轻数据库的负载压力。加速应用访问;解决分布式web部署的session同步问题,状态缓存。缓存包括会话会话状态和应用程序横向扩展时的状态数据。这类数据一般很难恢复,对可用性要求很高。高可用性集群。并行处理。通常涉及大量需要共享的中间计算结果;云计算领域提供分布式缓存服务。分布式缓存对比:MemcacheVSRedis1,Redis不仅支持简单的k/v类型数据,还提供list、set、zset、hash等数据结构的存储。Memcache只支持简单的数据类型,复杂的对象需要客户端自己处理。2、Redis支持数据持久化,可以将内存中的数据保存在磁盘上,重启时可以再次加载(PS:持久化在rdb、aof中)。3、由于Memcache没有持久化机制,宕机后缓存的数据全部失效。Redis配置为持久化。停机后重启后,停机时的数据会自动加载到缓存系统中。具有较好的容灾机制。4、Memcache可以在客户端使用Magent进行一致性哈希进行分发。Redis支持服务器端分布式(PS:Twemproxy/Codis/Redis-cluster多种分布式实现方式)5.Memcached简单的限制就是key(键)和Value的限制。***密钥长度为250个字符。可接受的存储数据不能超过1MB(可修改的配置文件变大),因为这是典型slab的最大值,不适合虚拟机。Redis的key长度最大支持512k。6、Redis采用单线程模型,保证数据按顺序提交。Memcache需要使用cas来保证数据的一致性。CAS(CheckandSet)是一种保证并发一致性的机制,属于“乐观锁”的范畴。原理很简单:取版本号,操作,比较版本号,一致则操作,不一致则放弃任何操作CPU占用率。由于Redis只使用单核,而Memcached可以使用多核,平均而言,每个核上的Redis在存储小数据时的性能要高于Memcached。在100k以上的数据中,Memcached的性能要高于Redis。7.Memcache内存管理:使用SlabAllocation。原理很简单,预先分配一系列固定大小的组,然后根据数据大小选择最合适的块存储。避免内存碎片。(缺点:不能改成length,浪费一定的空间)memcached默认下一个slab的最大值是上一个slab的1.25倍。8、Redis内存管理:Redis通过定义一个数组来记录所有的内存分配。Redis使用封装的malloc/free,比Memcached的内存管理方式简单多了。因为malloc首先以链表的形式在托管内存中搜索可用空间分配,导致内存碎片较多。分布式缓存选型总结其实,企业选择Memcache和Redis,更多的应该是基于业务的使用场景(因为Memcache和Redis都有足够高的性能和稳定性)。如果业务场景需要使用持久化缓存功能,或者支持多种数据结构的缓存功能,那么Redis是最佳选择。(PS:Redis的集群方案也比Memcache好,Memcache是??客户端一致性哈希集群方案,而Redis采用的是无中心的服务器端集群方案。)总结一下:为了让缓存系统能够支持更多的业务场景,选择Redis会更好。分布式缓存的常见问题和挑战1.缓存雪崩缓存雪崩可以简单理解为:由于原缓存失效,新的缓存还没有过期(例如:当我们设置了相同过期时间的缓存时,同时出现大面积缓存过期),所有本该访问缓存的请求都得去查询数据库,给数据库CPU和内存带来巨大的压力,严重的会导致数据库下去。从而形成一连串的连锁反应,导致整个系统崩溃。2、缓存穿透缓存穿透是指用户查询的数据,在数据库中不存在,自然也不存在缓存中。这样当用户查询的时候,在缓存中是找不到的,每次用户都得去数据库重新查询,然后返回空(相当于两次无用的查询)。这样请求就绕过了缓存,直接去查数据库,这也是经常提到的缓存效率问题。3、缓存预热缓存预热应该是一个比较常见的概念。相信很多小伙伴应该都能很容易理解,缓存预热就是在系统上线后直接加载相关的缓存数据到缓存系统中。这样可以避免用户请求时先查询数据库,再缓存数据的问题!用户直接查询已经提前预热好的缓存数据!4.缓存更新除了缓存服务器自带的缓存失效策略外,我们还可以根据具体业务需求自定义缓存淘汰。常见的策略有两种:(1)定期清理过期缓存;(2))当有用户请求时,再判断本次请求使用的缓存是否过期。如果过期,则去底层系统获取新数据,更新缓存。两者各有优缺点。第一个缺点是维护大量的缓存键比较麻烦。第二个缺点就是每次用户请求缓存都要判断无效,逻辑比较复杂!使用哪种方案取决于你自己的应用场景。5、缓存降级当访问量激增,服务出现问题(如响应时间慢或无响应),或非核心服务影响核心进程性能时,仍需保证服务正常运行仍然可用,即使它是损坏的服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现手动降级。降级的最终目标是保持核心服务可用,即使有损。并且有些服务是不能降级的(比如加入购物车,结账)。降级前,需要对系统进行梳理,看系统能否保持安全;从而分清哪些必须死守,哪些可以降级;例如,可以参考日志级别设置方案:(1)General:比如某些服务偶尔会因为网络抖动或者服务在线超时而自动降级;(2)警告:部分服务在一段时间内成功率有波动(比如在95%到100%之间),可自动降级或手动降级,并发出告警;(3)错误:比如可用率低于90%,或者数据库连接池炸毁,或者流量突然增加到系统可以承受的最大阈值。这时候可以根据情况自动降级或者手动降级。;(4)严重错误:比如由于特殊原因导致数据错误,此时需要紧急手动降级。