背景说明
分布式缓存中为了可用性及高性能的考虑,可以使用如下一种master/slave设计模式。
图中的proxy是逻辑的概念,可以是基于client的包装实现,也可以是独立的proxy服务,但本文大部分是指独立的服务。几个主要的问题说明如下。
为什么cache要使用两个集群((master/slave)来存放?
主要出于可用性及高性能的考虑。传统的架构使用基于一致性哈希的分布式缓存,数据只存在一份副本,在出现cache节点单点故障时,虽然可以由一致性哈希算法将请求均匀落到其他节点,但由于穿透的请求较多,仍然给数据库带来较大的访问压力。为了避免对数据穿透带来的冲击,数据使用两份副本可以避免穿透的问题。同时在数据访问较大时候,也可以更好的分担流量,避免峰值单份数据跑满对系统带来的冲击。
为什么两份副本要使用master/slave结构?
由于大型系统中通常存在多个client同时操作同一份数据,需要确保所有client对数据修改时数据的一致性。为了避免两cluster两份副本数据不一致带来的困扰,使用了一个简单的做法,在配置中人为指定一个cluster为master,所有的数据以master为准。
为什么一些场景需要使用CAS?
CAS在计算机并发领域通常指Compare-and-swap,在memcached中,也称为Check And Set. 在分布式系统中,一份数据可能同时被多个调用修改,比如微博中的@箱,一个用户同时收到多个@的情况还是比较常见,比如当原来@箱里面记录是{1,2,3}时,4和5由不同的调用来源同时到达,如果没有同步的保护,系统的数据有可能最终被写成{1,2,3,4}或{1,2,3,5},由于memcached没有原生的list结构,list都是一个自定义的value, 则很容易出现client A覆盖了同时在写的client B的数据。因此假如两个调用方同时读到{1,2,3}时,第一个写入{1,2,3,4}会成功,后续的{1,2,3,5}CAS写入就会失败,因为此时服务器已经不是{1,2,3}了,失败的调用向服务端取回{1,2,3,4},最终写入{1,2,3,4,5}
在master/slave场景,比起普通的memcache CAS有什么区别?
目前的做法是master cas成功之后,直接修改slave,并不同时在slave执行cas操作。由于数据存在两份副本,当数据不一致时,无法自动处理数据的不一致冲突。因此在实践上只以master操作为准。
为什么使用proxy?
使用proxy主要是出于可用性、命中率以及可运维方面的考虑
可用性与可运维:当进行服务器增容或缩容时,如果client的数量较大,如果未使用proxy模式,client所在服务器通常需要修改配置并且逐个重启。重启(系统维护)一方面带来可用性方面的问题,运维方面也较为繁琐。
命中率:如果业务场景需要较高的命中率(比如>90%),则增容或缩容就变得较为复杂,需要client配合做一些策略,比如扩容后仍然访问扩容前旧的节点的数据以保证命中率。如果用proxy模式则极大降低client的访问复杂性,将相关逻辑都封装在proxy之后。
分布式缓存的一起问题
最近某业务有一起master单点故障,导致在问题的时间段内,用户看不到最近发生变更的数据。由于在上述场景中,实现cas时候的流程如下
1) master.cas(k,v)
2) 如果1成功,slave.set(k,v)
3) 如果1失败,不执行slave.set(),直接return;
由于第三步在失败时,并不会set slave,导致数据出现一致性问题,即使slave依然可用,新的数据不会写入cache。
首先看在master failure时,为什么不切换到slave cas?
先说自动切换的问题
上文也提过,两份数据副本在出现数据不一致后,并不能自动仲裁达到最终一致性,但是指定master角色可以达到最终一致性。如果master角色可以由调用方自动切换,则会带来数据的混乱。调用方存在多个节点,至少需要统一的config server来保证切换的一致性。另外,自动切换发生后,无法达到两份数据的最终一致性。
再说由运维手工切换
由于不牵涉到代码的逻辑判断,虽然切换也会带来一些数据一致性问题,在具体场景下(比如master长久宕机)切换可以接受。
在出现上述问题后,其他一些解决方案如下。
1. proxy在master cas失败时候delete slave data
2. client在master cas失败时set slave, 并且将数据过期时间设成5分钟
上述方案很难完美,一些明显存在的问题如下
方案1:
命中率的问题。由于delete导致修改的数据迅速失效,会导致读取量的增加,在读写均密集的业务场景,可能会导致数据访问出现波动。
接口职责单一性的问题。proxy在cas调用中隐藏了删除数据的逻辑,这是一个未在正常期望范围内的额外操作,在特殊情况下,可能会导致不可预料的情况出现。(尽管在实际操作中proxy提供配置开关选项)
方案2:
依然是命中率的问题,5分钟过期延缓了过期的访问数据库的压力,但相关压力仍然会传递到数据库。
希望通过上面说明读者能理解这个场景的问题。在这个场景下,完美的方案应当如何设计?
相关推荐
分布式缓存作为一种在多节点之间共享和分布数据的存储方式,是现代大型分布式系统中不可或缺的一个组件。它能够有效降低数据库的读写压力,加速数据访问速度,提高系统的响应性能。在分布式缓存的实现方式中,基于...
在分布式环境中,Ehcache通过使用JGROUP来实现分布式缓存。JGROUP是一个用于构建可靠集群通信的库,可以提供组成员资格、故障检测、传输协议等多种功能,使得Ehcache能够在多个节点之间共享和同步缓存数据。Ehcache...
本地缓存与分布式缓存优缺点、使用场景 缓存是计算机系统中的一种优化技术,通过将频繁访问的数据存储在内存中,以减少对外部存储设备的访问次数,提高系统的响应速度和性能。本文将详细介绍本地缓存与分布式缓存的...
【基于Redis的分布式缓存系统架构分析】 在现代高并发的互联网应用中,为了提高数据访问的速度和系统性能,往往采用缓存技术。基于Redis的分布式缓存系统因其高效、灵活的特点,被广泛应用于大型应用系统中。Redis...
Hadoop分布式缓存是Hadoop生态系统中的一个重要组成部分,它允许应用程序在执行MapReduce任务时共享和重用数据,从而提高整体性能。这份源码提供了深入理解Hadoop如何管理和利用分布式缓存的机会,对于想要优化...
分布式缓存服务器Memcached是互联网应用中广泛使用的内存对象缓存系统,用于减轻数据库的负载,提高应用程序的性能。Memcached的设计目标是简单且高效,它通过在内存中存储数据来提供快速的数据访问。让我们深入了解...
实验结果表明,Redis分布式缓存的吞吐率与集群规模有较好的线性关系,所提出的方法能够较好地解决Hadoop任务对共享数据的访问问题。 下面是相关的知识点: 1. 分布式缓存技术:分布式缓存技术是指将数据缓存在多个...
分布式缓存-基于Redis集群解决单机Redis存在的问题。分布式缓存-基于Redis集群解决单机Redis存在的问题。分布式缓存-基于Redis集群解决单机Redis存在的问题。分布式缓存-基于Redis集群解决单机Redis存在的问题。...
本资料"30_分布式缓存相关面试题的回答技巧总结.zip"聚焦于Java领域的分布式缓存,包含了笔记.docx和PPT.pptx两个文件,旨在帮助求职者掌握面试中可能遇到的分布式缓存相关问题及其解答策略。 1. **什么是分布式...
本文将深入探讨Ehcache作为JVM缓存和分布式缓存的角色,以及Redis作为分布式缓存的解决方案,包括其分片集群、哨兵系统、数据结构、主从复制以及避免缓存问题的策略。 首先,我们了解为什么需要使用缓存。缓存的...
分布式缓存进一步解决了单应用服务器缓存因集群化部署而导致的缓存一致性问题,通过第三方中间件的形式,实现了集群化管理和操作。 分布式缓存系统可以配置为重复或分配两种方式。重复配置(Replication)将数据...
在分布式系统中,缓存问题尤为重要,因为分布式系统通常由多台计算机组成,它们分布在不同的地理位置,通过网络连接协同工作。由于网络延迟的存在,合理的缓存策略显得尤为关键。在分布式缓存系统中,选择合适的缓存...
分布式缓存是现代大型互联网应用中不可或缺的一部分,它能够有效地解决单机缓存容量有限以及高并发场景下的数据访问性能问题。本项目基于C#语言实现了分布式缓存系统,提供了详细的类库使用说明,旨在帮助开发者更好...
**分布式缓存技术** 分布式缓存是一种在分布式系统中存储数据的机制,它可以在多台机器之间共享数据,提供高速访问并减轻数据库的压力。在大型应用程序中,分布式缓存是性能优化的关键技术,尤其对于处理高并发和大...
分布式缓存技术是为了解决大型分布式系统中的数据存储、数据处理等问题而产生的,其核心思想是将数据尽可能地在离用户最近的节点上缓存,以提高数据访问的速度和系统的吞吐量。 分布式缓存技术在云计算环境下所面临...
分布式缓存是解决大型互联网应用高并发访问和大数据量存储问题的关键技术之一。Redis凭借其内存存储特性、丰富的数据结构以及高效的命令操作,成为了业界首选的分布式缓存解决方案。它能够快速读取和写入数据,减轻...
redis分布式缓存+spring整合及 集群、分片等配置使用例子
在实际应用中,分布式缓存系统需要解决的关键技术问题包括数据的高并发读写、数据的一致性和系统容错性等。例如,通过分布式Hash表和集群路由算法,客户端可以将请求映射到特定的数据节点进行处理,这样的设计可以...