分布式缓存的最佳实践案例分析
- 格式:docx
- 大小:839.71 KB
- 文档页数:17
利用云中间件实现分布式缓存的最佳实践随着云计算的快速发展,越来越多的企业和开发者开始意识到分布式缓存的重要性。
分布式缓存可以提高系统的性能和可扩展性,但要实现最佳实践,就需要利用云中间件的特性和功能。
本文将探讨如何利用云中间件实现分布式缓存的最佳实践。
1. 云中间件简介云中间件是一种由云服务提供商提供的基础设施软件,它可以提供各种云计算支持服务。
常见的云中间件包括阿里云的Redis、腾讯云的Memcache以及AWS的ElastiCache等。
云中间件可以提供高性能、可扩展性好、高可靠性和弹性的分布式缓存服务。
2. 分布式缓存的意义在传统的单机环境下,应用程序通常使用本地内存来存储缓存数据。
但随着应用程序规模的增大,本地内存容量不足的问题逐渐显现。
而分布式缓存可以解决这个问题,它将缓存数据分散存储在多台服务器上,提高了缓存容量和访问速度。
同时,分布式缓存还可以提高系统的可扩展性,可以根据需求增加或减少缓存节点。
3. 利用云中间件实现分布式缓存的优势云中间件提供了许多功能和特性来支持分布式缓存的实现。
首先,云中间件可以自动管理缓存节点的扩容和缩容,根据实际需求进行自动伸缩,提高了系统的弹性和可用性。
其次,云中间件可以提供高可用的缓存服务,通过数据冗余和备份策略来确保数据的安全性。
此外,云中间件还可以提供监控、报警和故障恢复等功能,帮助开发者更好地管理和维护分布式缓存系统。
4. 实践步骤实现分布式缓存的最佳实践需要按照以下步骤进行:1)选择合适的云中间件:根据自己的需求和实际情况选择合适的云中间件。
不同的云中间件在性能、功能和价格等方面可能有所不同,开发者需要根据自己的需求进行选择。
2)设计缓存策略:根据应用程序的特点和性能需求,设计合适的缓存策略。
缓存策略包括缓存对象的选择、缓存键的设计、缓存有效期的设置等。
合理的缓存策略可以提高系统的性能和可用性。
3)配置云中间件:根据具体的云中间件的要求,进行配置和部署。
分布式缓存设计缓存是提高系统性能的关键组件之一,而分布式缓存则在分布式系统的环境下实现了数据的共享和高效访问。
本文将介绍分布式缓存的设计原理和实践,以及一些常见的分布式缓存方案。
一、缓存的作用缓存是将计算结果、数据库查询结果等常用数据存储在高速读写的存储介质中,以提高系统的性能和响应速度。
在分布式系统中,缓存的作用尤为重要,可以减轻后端数据库的压力,提高系统的可扩展性和可用性。
二、分布式缓存的设计原则1. 数据一致性:分布式缓存需要保证数据的一致性,即缓存中的数据和后端存储中的数据保持同步。
常见的解决方案包括使用缓存更新策略、缓存伪装技术等。
2. 高可用性:分布式缓存需要保证在各种异常情况下都能够正常工作,如节点故障、网络分区等。
常见的解决方案包括使用数据复制、故障检测与恢复机制等。
3. 高性能:分布式缓存需要具备快速读写的能力,以满足系统对高并发读写的需求。
常见的解决方案包括使用缓存预热、数据分片、分布式存储等。
4. 可扩展性:分布式缓存需要支持系统的水平扩展,以应对日益增长的数据访问需求。
常见的解决方案包括使用分布式哈希、一致性哈希等。
三、常见的分布式缓存方案1. Redis:Redis 是一个开源的高性能分布式缓存系统,支持多种数据结构和丰富的功能,如持久化、发布订阅、事务等。
它通过将数据存储在内存中,提供了非常快速的读写性能。
2. Memcached:Memcached 是一个免费的、高性能的分布式内存对象缓存系统,适用于访问模式相对简单的场景。
它通过缓存的方式,将数据存储在内存中,从而提供快速的数据访问速度。
3. Hazelcast:Hazelcast 是一个开源的分布式缓存和计算平台,支持多种数据结构和分布式计算模型。
它可以无缝地集成到 Java 应用中,提供快速的数据访问和计算能力。
四、分布式缓存的设计实践1. 数据划分:根据业务需求和数据访问特点,将数据划分到不同的缓存节点中。
可以采用按数据分片方式,将数据均匀地分布在不同的节点上,提高并发读写能力。
Redis高性能分布式缓存解决方案Redis是一种开源的内存数据存储系统,用于存储和检索各种类型的数据结构,如字符串、哈希、列表、集合和有序集合等。
由于其快速、可扩展和高可用性的特点,Redis被广泛应用于缓存、消息队列、实时分析等场景。
本文将介绍Redis在分布式缓存方面的应用,以及如何提高其性能。
一、Redis作为分布式缓存的优势作为一种分布式缓存解决方案,Redis具有以下优势:1. 高速读写能力:Redis数据存储在内存中,读写速度极快,可以达到十万级的QPS(每秒查询数)。
2. 高并发支持:Redis采用单线程模型,通过事件驱动机制来实现高并发支持,有效地减少了上下文切换和线程间的竞争,保证了高性能。
3. 丰富的数据结构:Redis支持多种数据结构,如字符串、哈希、列表、集合和有序集合等,方便开发者根据实际需求选择合适的数据结构。
4. 内存淘汰策略:Redis提供了多种内存淘汰策略,如LRU(最近最少使用)、TTL(过期时间)、随机淘汰等,可以灵活地控制内存使用,避免内存溢出。
二、Redis分布式缓存方案设计在设计Redis分布式缓存方案时,需要考虑以下几个因素:1. 数据分片:将数据均匀地分布在不同的Redis节点上,以提高并行处理能力和容量。
2. 数据一致性:确保不同节点上的相同数据保持一致,避免数据冲突和错误。
3. 故障容错:当某个节点出现故障时,其他节点能够接替其工作,保证系统的可用性。
基于以上考虑,可以采用以下设计方案:1. 分片策略:采用一致性哈希算法(Consistent Hashing),将数据根据其键值哈希结果映射到不同的Redis节点上。
这样可以保证在节点的增加或减少时,最小化数据迁移的需求。
2. 数据复制:对于每个分片的数据,可以采用主从复制的方式进行备份。
主节点负责写操作,从节点负责读操作,以提高读写并发能力和可用性。
3. 故障检测和恢复:通过监控节点的健康状况,当节点发生故障时,可以自动将其从集群中移除,并将其负载转移到其他可用的节点上。
分布式数据库在电子商务领域中的应用案例随着电子商务的高速发展,越来越多的企业开始关注分布式数据库的应用,以提高系统性能和可靠性。
本文将介绍一些分布式数据库在电子商务领域中的应用案例,并分析其优势和挑战。
一、案例一:云商平台的订单管理系统云商平台是一个集多家商家和消费者于一体的综合性电子商务平台。
为了满足不同商家的需求,订单管理系统需要支持高并发、高可用和分布式的特性。
因此,分布式数据库成为最佳选择。
通过将订单数据分散存储在多个数据库节点上,可以提高系统的读写性能。
同时,通过数据的冗余备份和分布,可以实现高可用性,即使某个节点出现故障,其他节点仍然可以正常工作,不会影响到整个系统的运行。
然而,在实施分布式数据库时也需注意一些挑战。
首先,由于数据分布在不同节点上,数据的一致性和一致性维护成为主要问题。
其次,跨节点的事务处理也需要更加复杂的处理方式来保证正确性和完整性。
因此,在设计和实现过程中,需要充分考虑这些挑战。
二、案例二:大型电商平台的用户管理系统大型电商平台拥有海量的用户数据,用户管理系统需要能够高效地处理用户的注册、登录和个人信息修改等操作。
为了满足这些需求,分布式数据库成为不可或缺的工具。
通过将用户数据分布在多个数据库节点上,可以提高读写性能和并发处理能力。
此外,由于用户数据的重要性,分布式数据库的冗余备份机制也能够为系统提供高可靠性和容错能力。
然而,分布式数据库的广泛应用也带来了一些新问题。
例如,如何保证用户数据的一致性和安全性,如何进行跨节点的查询和分析等。
解决这些问题需要设计和实现复杂的分布式算法和策略,需要系统工程师具备高度的专业知识和技术能力。
三、案例三:物流管理系统的数据存储与分析电子商务中的物流管理起着至关重要的作用。
为了提高物流效率和准确性,物流管理系统需要能够存储和分析大量的物流数据,并根据数据进行智能决策。
分布式数据库的应用可以解决大数据量和高并发的挑战。
通过将物流数据分布在多个节点上,可以提高系统的读写性能和并发处理能力。
在Docker中实现分布式缓存的方案设计在计算机科学和软件开发中,缓存是一种重要的技术,它可以显著提高系统的性能和响应速度。
在分布式系统中,缓存的设计尤为重要,因为它可以有效地减少网络通信和数据存取的开销。
本文将探讨如何在Docker容器中实现分布式缓存的方案设计。
一、分布式缓存的需求和挑战在分布式系统中,不同的节点可能需要频繁地共享和访问相同的数据。
如果每次数据访问都需要从数据库或外部系统中获取,将会导致性能瓶颈和延迟。
为了解决这个问题,可以引入缓存机制。
然而,分布式缓存也面临一些挑战。
首先,数据一致性是一个关键问题。
如果不同节点上的缓存数据不一致,将会导致数据错误和不一致的结果。
其次,分布式缓存需要具备高可用性和可扩展性,以应对高并发和大规模数据的访问。
二、Docker容器的优势和应用Docker是一种轻量级的容器技术,它可以将应用程序以及其所依赖的软件环境打包成容器,并可以在不同的主机上运行。
Docker的优势在于可移植性、可复用性和高效性。
使用Docker容器来实现分布式缓存可以带来很多好处。
首先,Docker容器可以在不同的主机上部署,从而实现分布式缓存的高可用性和可扩展性。
其次,Docker容器的轻量级性质使得它可以更高效地利用系统资源,提高缓存系统的性能。
三、设计方案1.选择合适的缓存技术在选择缓存技术时,需要考虑系统的需求和数据特点。
常见的缓存技术有Redis、Memcached等。
Redis是一种高性能的键值存储系统,支持丰富的数据结构和复杂的查询操作。
Memcached是一个基于内存的缓存系统,适合存储简单的键值对。
根据实际需求选择合适的缓存技术。
2.部署容器集群使用Docker容器来实现分布式缓存,需要首先部署容器集群。
可以使用Docker Swarm或Kubernetes等容器编排工具来管理和调度容器。
将缓存节点分布到不同的主机上,可以实现负载均衡和故障恢复。
3.配置数据复制和持久化为了保证数据的一致性和持久性,需要配置数据复制和持久化机制。
数据库缓存技术与应用场景分析数据库缓存是一种常用的技术,用于提高数据库的访问速度和性能。
在本文中,我们将探讨数据库缓存的原理、常见的缓存技术以及其在不同应用场景下的使用。
首先,让我们了解一下数据库缓存的基本原理。
数据库缓存是指将数据库中的数据预先存储在高速缓存中,以免频繁地从数据库中读取数据。
这样可以大幅提高数据库的读取速度,并且减轻数据库服务器的负载。
常见的数据库缓存技术包括内存缓存、分布式缓存和查询缓存。
内存缓存是将数据库中的数据存储在内存中,以便快速访问。
通过将常用的数据加载到内存中,并使用高效的数据结构,如哈希表或红黑树,可以极大地提高数据库的读取性能。
内存缓存通常与数据库系统紧密集成,例如,MySQL中的InnoDB引擎通过使用内存缓存技术来提高读取速度。
分布式缓存是将数据存储在多台服务器中,可以通过在缓存节点之间进行数据的划分和复制来提高可扩展性和容错性。
常用的分布式缓存系统包括Redis和Memcached。
通过在数据库查询前先在缓存中查找数据,可以减少对数据库的访问次数,并提高响应速度。
此外,分布式缓存还可以用于会话管理、数据共享和负载均衡等应用场景。
查询缓存是指将查询结果缓存起来,以便下次查询时可以直接返回结果,而不必再执行查询操作。
查询缓存通常与数据库管理系统集成,在执行查询语句之前会首先检查缓存中是否存在相应的结果。
如果存在,则直接返回缓存结果,否则执行查询操作并将结果缓存起来。
虽然查询缓存可以提高读取性能,但在写入频繁的情况下可能会导致缓存过期或失效。
数据库缓存技术在许多应用场景中得到了广泛的应用。
首先,数据库缓存常用于读取密集型应用。
在读取密集型场景下,频繁的数据库查询会成为性能瓶颈。
通过使用数据库缓存,可以将热门数据缓存到内存中,从而大幅提高读取速度。
其次,数据库缓存还可以应用在大规模数据分析和报表生成中。
在大规模数据分析和报表生成过程中,通常需要对大量的数据进行聚合和计算。
分布式多实例数据库连接池缓存方案设计分布式多实例数据库连接池缓存方案需要考虑多方面的因素,包括数据库类型、负载均衡、连接池管理、缓存策略等。
下面是一个简单的概要:1. 数据库类型和分片策略选择:-数据库类型:选择合适的分布式数据库,例如MongoDB、Cassandra、CockroachDB等,根据应用的需求和性能特点选择最适合的数据库。
-分片策略:使用合适的分片策略,确保数据分布均匀,避免热点问题。
可以考虑按照业务特点进行垂直或水平分片。
2. 负载均衡:-使用负载均衡器确保请求被均匀地分配到各个数据库实例,防止某个实例成为瓶颈。
-考虑使用动态负载均衡策略,根据实例的负载情况动态调整流量分配。
3. 连接池管理:-连接池配置:配置合适的连接池参数,包括最小连接数、最大连接数、连接超时等。
-连接池监控:监控连接池的状态,实时了解连接数、连接请求等情况,做好报警和调整。
4. 缓存策略:-查询缓存:对于读密集型操作,可以考虑使用缓存,减轻数据库压力。
使用合适的缓存方案,如Redis、Memcached等。
-缓存更新策略:对于写操作,及时更新缓存,避免脏数据。
可以使用缓存失效策略,或者在写入数据库的同时更新缓存。
5. 事务管理:-对于涉及多个数据库实例的事务,确保使用分布式事务管理,以保证数据的一致性。
-考虑使用两阶段提交(2PC)或者柔性事务(Saga)等分布式事务协议。
6. 故障处理:-实现故障转移机制,当某个数据库实例发生故障时,能够快速切换到其他正常的实例。
-使用健康检查机制,定期检查数据库实例的状态,及时发现并处理故障。
7. 安全性:-数据库连接的安全性是至关重要的,确保连接是加密的,使用合适的身份验证机制。
8. 性能监控和调优:-定期监控系统性能,进行性能调优,保证系统在高负载时仍能提供良好的性能。
-使用性能监控工具和日志记录,帮助排查潜在问题。
这些是一个基本的框架,具体的实现还需要结合你的应用特点和具体的技术栈来进行调整。
Redis实时数据缓存与分布式计算的最佳实践Redis(Remote Dictionary Server)是一款开源的高性能键值对存储系统,它提供了丰富的数据结构和功能,并且具备快速读写能力。
在实时数据缓存和分布式计算领域,Redis已经成为了一种最佳实践的选择。
本文将介绍Redis在实时数据缓存和分布式计算方面的应用。
一、实时数据缓存实时数据缓存是现代应用程序中经常遇到的问题,特别是在需要处理大量实时数据的场景下。
Redis作为一个高性能的缓存系统,可以帮助应用程序有效地缓存数据,提高系统的响应速度和并发处理能力。
1.1 缓存热点数据在大多数应用程序中,存在一些访问频率较高的数据,我们称之为热点数据。
通过将这些热点数据缓存到Redis中,可以避免频繁地访问数据库,减轻数据库的压力,提高系统的性能。
同时,Redis支持持久化功能,即将数据存储到硬盘中,确保数据的安全性和可靠性。
1.2 缓存数据过期策略对于实时数据缓存,数据的实效性是非常重要的。
Redis提供了灵活的过期策略,可以根据实际需求设置数据的过期时间。
通过设置适当的过期时间,可以避免缓存数据过期而导致的数据不一致性问题。
1.3 发布订阅模式在实时数据缓存场景中,往往需要将数据实时地推送给客户端。
Redis提供了发布订阅(Pub/Sub)模式,可以将缓存的数据实时地发布给订阅者。
通过发布订阅模式,可以实现实时数据的即时更新,满足实时性要求。
二、分布式计算随着互联网和大数据技术的发展,分布式计算成为了一种必要的解决方案。
Redis作为一个分布式缓存和消息队列系统,可以辅助实现分布式计算任务。
2.1 分布式锁在分布式计算中,往往需要协调多个节点的并发访问。
Redis提供了分布式锁的功能,通过对共享资源进行加锁和解锁操作,实现对并发访问的控制。
分布式锁可以确保多个节点的访问行为是有序的,避免了数据不一致的问题。
2.2 分布式插槽Redis支持数据的分片存储,将数据分散到多个节点上进行存储和计算。
分布式缓存解决方案随着互联网应用的发展和用户量的激增,对系统性能和响应速度的要求也越来越高。
而分布式缓存作为一种常见的解决方案,在提升系统性能方面发挥着重要的作用。
本文将介绍什么是分布式缓存以及常见的分布式缓存解决方案。
一、什么是分布式缓存分布式缓存是指将缓存数据存储和处理分布在多台计算机节点上,通过统一的接口对外提供缓存服务。
相比于单机缓存,分布式缓存具有多台节点可扩展性好、容错性强的优点,能够有效提高系统的性能和可用性。
二、常见的分布式缓存解决方案1. MemcachedMemcached是一种广泛应用、轻量级的开源分布式缓存解决方案。
它采用内存存储数据,通过哈希分区将数据分布在多台服务器上,实现数据的快速读写。
Memcached具有高性能、简单易用的特点,适用于缓存热点数据、加速数据库访问等场景。
2. RedisRedis是一种高性能、高可用的开源分布式缓存和存储系统。
它支持丰富的数据结构和功能,如字符串、哈希表、列表、集合、有序集合等,并提供了多种持久化方式。
Redis通过主从复制和分片等机制实现数据的高可用和水平扩展。
它适用于缓存、消息队列、分布式锁等场景。
3. HazelcastHazelcast是一种基于Java的开源分布式数据存储和计算平台,其中包含了分布式缓存功能。
它提供了分布式数据结构和分布式计算接口,支持多种数据模型,如Map、List、Set、Queue等。
Hazelcast具有良好的可扩展性和可靠性,适用于分布式计算、缓存共享等场景。
4. CouchbaseCouchbase是一种面向文档的分布式数据库,但也提供了内置的缓存功能。
它采用Memcached协议和Redis协议实现缓存功能,并支持多数据中心复制、跨数据中心同步等高级特性。
Couchbase具有高可用、高性能、水平扩展的优点,适用于大规模数据存储和缓存的场景。
三、如何选择分布式缓存解决方案在选择分布式缓存解决方案时,需要考虑以下几个方面的因素:1. 需求场景:根据具体的业务需求,选择适合的分布式缓存解决方案。
minio分布式存储案例
MinIO是一个开源的分布式对象存储服务,它可以轻松地部署
在私有云、公共云或混合云环境中。
MinIO的设计目标是提供高性能、可扩展、安全的对象存储解决方案,适用于大规模数据存储和
管理。
以下是一些MinIO分布式存储的典型应用案例:
1. 企业数据湖,许多企业需要存储和管理海量的数据,以支持
数据分析、机器学习和人工智能等应用。
MinIO可以作为企业数据
湖的基础设施,提供高性能的对象存储服务,满足企业对数据存储
和管理的需求。
2. 大规模媒体存储,媒体行业需要存储大量的音频、视频和图
像文件。
MinIO可以作为媒体存储平台的基础设施,提供高可用性
和可扩展性的存储服务,以满足媒体行业对大规模媒体文件存储和
传输的需求。
3. 云原生应用,许多云原生应用需要可靠的对象存储服务来存
储和管理应用程序的数据。
MinIO可以作为云原生应用的存储后端,
提供高性能和可扩展的对象存储服务,以满足云原生应用对存储的需求。
4. 备份和归档,许多企业需要对数据进行备份和归档,以满足合规性和灾难恢复的需求。
MinIO可以作为备份和归档解决方案的基础设施,提供高可用性和安全的对象存储服务,以满足企业对备份和归档的需求。
总之,MinIO分布式存储可以应用于各种场景,包括企业数据湖、大规模媒体存储、云原生应用和备份归档等,为用户提供高性能、可靠性和安全性的对象存储服务。
分布式缓存的最佳实践案例分析本文主要介绍使用分布式缓存的优秀实践和线上案例。
这些案例是笔者在多家互联网公司里积累并形成的优秀实践,能够帮助大家在生产实践中避免很多不必要的生产事故。
一、缓存设计的核心要素我们在应用中决定使用缓存时,通常需要进行详细的设计,因为设计缓存架构看似简单,实则不然,里面蕴含了很多深奥的原理,如果使用不当,则会造成很多生产事故甚至是服务雪崩之类的严重问题。
笔者在做设计评审的过程中,总结了所有与缓存设计相关的设计点,这里列出来供大家参考。
1、容量规划∙缓存内容的大小∙缓存内容的数量∙淘汰策略∙缓存的数据结构∙每秒的读峰值∙每秒的写峰值2、性能优化∙线程模型∙预热方法∙缓存分片∙冷热数据的比例3、高可用∙复制模型∙失效转移∙持久策略∙缓存重建4、缓存监控∙缓存服务监控∙缓存容量监控∙缓存请求监控∙缓存响应时间监控5、注意事项∙是否有可能发生缓存穿透∙是否有大对象∙是否使用缓存实现分布式锁∙是否使用缓存支持的脚本(Lua)∙是否避免了Race Condition笔者在这里把这些设计点提供给读者,请读者在做缓存设计时把每一项作为一个思考的起点,思考我们在设计缓存时是否想到了这些点,以避免在设计的过程中因忽略某一项而导致严重的线上事故发生。
二、缓存设计的优秀实践笔者在做设计评审的过程中,总结了一些开发人员在设计缓存系统时的优秀实践,如下所述:优秀实践1缓存系统主要消耗的是服务器的内存,因此,在使用缓存时必须先对应用需要缓存的数据大小进行评估,包括缓存的数据结构、缓存大小、缓存数量、缓存的失效时间,然后根据业务情况自行推算在未来一定时间内的容量的使用情况,根据容量评估的结果来申请和分配缓存资源,否则会造成资源浪费或者缓存空间不够。
优秀实践2建议将使用缓存的业务进行分离,核心业务和非核心业务使用不同的缓存实例,从物理上进行隔离,如果有条件,则请对每个业务使用单独的实例或者集群,以减小应用之间互相影响的可能性。
笔者就经常听说有的公司应用了共享缓存,造成缓存数据被覆盖以及缓存数据错乱的线上事故。
优秀实践3根据缓存实例提供的内存大小推算应用需要使用的缓存实例数量,一般在公司里会成立一个缓存管理的运维团队,这个团队会将缓存资源虚拟成多个相同内存大小的缓存实例。
例如一个实例有4GB内存,在应用申请时可以按需申请足够的实例数量来使用,对这样的应用需要进行分片,详情请参考《可伸缩服务架构:框架与中间件》中4.4.3的内容。
这里需要注意,如果我们使用了RDB备份机制,每个实例使用4GB内存,则我们的系统需要大于8GB 内存,因为RDB备份时使用了copy-on-write 机制,需要fork出一个子进程,并且复制一份内存,因此需要双份的内存存储大小。
优秀实践4缓存一般是用来加速数据库的读操作的,一般先访问缓存后访问数据库,所以缓存的超时时间的设置是很重要的。
笔者曾经在一家互联网公司遇到过由于运维操作失误导致缓存超时设置得较长,从而拖垮服务的线程池,最终导致服务雪崩的情况。
优秀实践5所有的缓存实例都需要添加监控,这是非常重要的,我们需要对慢查询、大对象、内存使用情况做可靠的监控。
优秀实践6我们不推荐多个业务共享一个缓存实例,但是由于成本控制的原因,这种情况经常出现,我们需要通过规范来限制各个应用使用的key有唯一的前缀,并进行隔离设计,避免产生缓存互相覆盖的问题。
优秀实践7任何缓存的key都必须设定缓存失效时间,且失效时间不能集中在某一点,否则会导致缓存占满内存或者缓存雪崩。
优秀实践8低频访问的数据不要放在缓存中,如我们前面所说的,我们使用缓存的主要目的是提高读取性能。
曾经有个小伙伴设计了一套定时的批处理系统,由于批处理系统需要对一个大的数据模型进行计算,所以该小伙伴把这个数据模型保存在每个节点的本地缓存中,并通过消息队列接收更新的消息来维护本地缓存中模型的实时性,但是这个模型每个月只用了一次,所以这样使用缓存是很浪费的。
既然是批处理任务,就需要把任务进行分割,进行批量处理,采用分而治之、逐步计算的方法,得出最终的结果即可。
优秀实践9缓存的数据不易过大,尤其是Redis,因为Redis使用的是单线程模型,在单个缓存key的数据过大时,会阻塞其他请求的处理。
优秀实践10对于存储较多value的key,尽量不要使用HGETALL等集合操作,该操作会造成请求阻塞,影响其他应用的访问。
优秀实践11缓存一般用于在交易系统中加速查询的场景,有大量的更新数据时,尤其是批量处理时,请使用批量模式,但是这种场景较少。
优秀实践12如果对性能的要求不是非常高,则尽量使用分布式缓存,而不要使用本地缓存,因为本地缓存在服务的各个节点之间复制,在某一时刻副本之间是不一致的,如果这个缓存代表的是开关,而且分布式系统中的请求有可能会重复,就会导致重复的请求走到两个节点,一个节点的开关是开,一个节点的开关是关,如果请求处理没有做到幂等,就会造成处理重复,在严重情况下会造成资金损失。
优秀实践13在写缓存时一定要写入完全正确的数据,如果缓存数据的一部分有效、一部分无效,则宁可放弃缓存,也不要把部分数据写入缓存,否则会造成空指针、程序异常等。
优秀实践14在通常情况下,读的顺序是先缓存,后数据库;写的顺序是先数据库,后缓存。
优秀实践15在使用本地缓存(如Ehcache)时,一定要严格控制缓存对象的个数及声明周期。
由于JVM 的特性,过多的缓存对象会极大影响JVM的性能,甚至导致内存溢出等。
优秀实践16在使用缓存时,一定要有降级处理,尤其是对关键的业务环节,缓存有问题或者失效时也要能回源到数据库进行处理。
三、关于常见的缓存问题的线上案例笔者在多家互联网公司负责架构方案评审和线上事故复盘,这里列举其中的一些典型案例,供大家参考和借鉴。
案例1现象:某应用程序的数据库负载瞬时升高。
原因:在应用程序中对使用的大量缓存key设置了同一个固定的失效时间,当缓存失效时,会造成在一段时间内同时访问数据库,造成数据库的压力较大。
总结:在使用缓存时需要进行缓存设计,要充分考虑如何避免常见的缓存穿透、缓存雪崩、缓存并发等问题,尤其是对于高并发的缓存使用,需要对key的过期时间进行随机设置,例如,将过期时间设置为10秒+random(2),也就是将过期时间随机设置成10~12秒。
案例2现象:导致迁移前后两个系统的核心操作重复。
原因:在迁移的过程中,重复的流量进入了不同的节点,由于使用了本地缓存存储迁移开关,而迁移开关在开关打开的瞬间导致各个节点的开关状态不一致,有的是开、有的是关,所以对于不同节点的流量的处理重复,一个走了开关开的逻辑,一个走了开关关的逻辑。
总结:避免使用本地缓存来存储迁移开关,迁移开关应该在有状态的订单上标记。
案例3现象:某模块设计使用了缓存加速数据库的读操作的性能,但发现数据库负载并没有明显下降。
原因:由于这个模块的使用方查询请求的数据在数据库中不存在,是非法的数据,所以导致缓存没有命中,每次都穿透到数据库,且量级较大。
总结:在使用缓存时需要进行缓存设计,要充分考虑如何避免常见的缓存穿透、缓存雪崩、缓存并发等问题,尤其是对高并发的缓存使用,需要对无效的key进行缓存,以抵挡恶意的或者无意的对无效缓存查询的攻击或影响。
案例4现象:监控系统报警,Redis中单个哈希键占用的空间巨大。
原因:应用系统使用了哈希键,哈希键本身有过期时间,但是哈希键里面的每个键值对没有过期时间。
总结:在设计Redis的过程中,如果有大量的键值对要保存,则请使用字符串键的数据库类型,并对每个键都设置过期时间,请不要在哈希键内部存储一个没有边界的集合数据。
实际上,无论是对缓存、内存还是对数据库的设计,如果使用任意一个集合的数据结构,则都要考虑为它设置最大限制,避免内存用光,最常见的是集合溢出导致的内存溢出的问题。
案例5现象:某业务项目由于缓存宕机导致业务逻辑中断,数据不一致。
原因:Redis进行主备切换,导致瞬间内应用连接Redis异常,应用并没有对缓存做降级处理。
总结:对于核心业务,在使用缓存时一定要有降级方案。
常见的降级方案是在数据库层次预留足够的容量,在某一部分缓存出现问题时,可以让应用暂时回源到数据库继续业务逻辑,而不应该中断业务逻辑,但是这需要严格的容量评估,请参考《分布式服务架构:原理设计与实战》第3章的内容。
案例6现象:某应用系统负载升高,响应变慢,发现应用进行频繁GC,甚至出现OutOfMemroyError: GC overhead limt exceed的错误日志。
原因:因为这个项目是个历史项目,使用了Hibernate ORM框架,在Hibernate中开启了二级缓存,使用了Ehcache;但是在Ehcache中没有控制缓存对象的个数,缓存对象增多,导致内存紧张,所以进行了频繁的GC操作。
总结:使用本地缓存(如Ehcache、OSCache、应用内存)时,一定要严格控制缓存对象的个数及声明周期。
案例7现象:某个正常运行的应用突然报警线程数过高,之后很快就出现了内存溢出。
原因:由于缓存连接数达到最大限制,应用无法连接缓存,并且超时时间设置得较大,导致访问缓存的服务都在等待缓存操作返回,由于缓存负载较高,处理不完所有的请求,但是这些服务都在等待缓存操作返回,服务这时在等待,并没有超时,就不能降级并继续访问数据库。
这在BIO模式下线程池就会撑满,使用方的线程池也都撑满;在NIO模式下一样会使服务的负载增加,服务响应变慢,甚至使服务被压垮。
总结:在使用远程缓存(如Redis、Memcached)时,一定要对操作超时时间进行设置,这是非常关键的,一般我们设计缓存作为加速数据库读取的手段,也会对缓存操作做降级处理,因此推荐使用更短的缓存超时时间,如果一定要给出一个数字,则希望是100毫秒以内。
案例8现象:某项目使用缓存存储业务数据,上线后出现错误问题,开发人员束手无策。
原因:开发人员不知道如何发现、排查、定位和解决缓存问题。
总结:在设计缓存时要有降级方案,在遇到问题时首先使用降级方法,还要设计完善的监控和报警功能,帮助开发人员快速发现缓存问题,进而来定位和解决问题。
案例9现象:某项目在使用缓存后,开发测试通过,到生产环境后,服务却出现了不可预知的问题。
原因:该应用的缓存key与其他应用缓存key冲突,导致互相覆盖,出现逻辑错误。
总结:在使用缓存时一定要有隔离的设计,可以通过不同的缓存实例来做物理隔离,也可以通过各个应用的缓存key使用不同的前缀进行逻辑隔离。