如今,缓存系统的应用非常广泛,能够用来提高并发数、数据吞吐量,提高快速响应能力。那么当数据量达到一定程度,单机环境可能就显得有些力不从心了,就需要一个分布式缓存系统。
1.缓存系统的选择
图1-1
1.1缓存分类
如上图所示,首先缓存大致可以分为四大类。
cdn缓存:cdn即内容分发网络,cdn边缘节点将数据缓存起来。
反向代理缓存:如nginx的缓存。
本地缓存:代表的有ehcache和guavacache。
分布式缓存:各缓存系统。
1.2分布式缓存
本文主要探讨各分布式缓存系统,如图1-1所示,列出了五种:
其中evcache和aerospike使用场景不是那么通用和广泛。
evcache:是netflix的基于memcached&spymemcached的缓存方案。
aerospike:是可基于ssd的kvnosql数据库。
除此之外,还有三种常见缓存系统。
tair:阿里开源,跨机房、性能随结点添加线性上升、适用大数据量。tair还有三种引擎。
ldb:基于googleleveldb,支持kv和类hashmap结构,性能稍低,持久化可靠性最高。
mdb:基于memcache,支持kv和类hashmap,性能最优,不支持持久化存储。
rdb:基于redis。
memcache:不支持数据同步、分布式支持较差。
redis:社区活跃、使用最多。
综上所述,在一般情况下,考虑到适用性和稳定性,redis是搭建缓存系统的最优选择。以下将基于redis介绍。
2.redis集群缓存方案
如顶部图1-1所示,列出了redis的集群高可用的方案,基本可以分为三种。
2.1主从机制
常见的集群架构,搭建简单,主要实现读写分离和备份,可以由master负责读写,slave负责备份。但存在故障恢复复杂、水平拓展难、写能力受限等问题。结构图如下:
2.2哨兵机制
redissentinel是社区版本推出的原生高可用解决方案。由一或多个哨兵实例监视任意个主从服务器,且在master宕机时,自动将宕机服务器属下的slave服务器升级为主服务器,从而保证系统的可用性。较主从实现的监控、选主。但问题主要是要保证master的ha切换。结构图如下:
2.3“分布式”
到这里以上两种机制其实只能算作“集群”,并非严格意义上的“分布式”。接着来看看分布式方案。
集群强调高可用,分布式在集群的基础上又强调协作。
3.redis分布式缓存方案
任何分布式存储系统,首先面临的就是sharding(分片)问题,如顶部图1-1所示该问题有为三种解决方法。
3.1客户端分片
顾名思义,将数据分片的路由功能交给客户端,但这是一种静态分片,维护性差。基本是不予考虑的。
3.2代理分片
通过代理分发到具体的redis实例。有两个常用解决方案。
twemproxy:twitter开源,轻量级,不再维护,无法平滑地扩容/缩容,运维也不是很友好,性能一般。
codis:豌豆荚开源,支持水平拓展,运维平台完善,性能较twemproxy快。codis在国内使用的较多,同时代理分片的思路也有很多公司在此基础开发了自己的二次方案。不过codis也不再维护。
其实,这两种代理分片的方案,都是在redis官方未推出良好的分布式方案时的产生的,在官方更新提供更优策略后都不再维护。
3.3服务器端分片
这就要谈到redis官方方案redis-cluster。
在redis3.0之前是没有较好的分布式方案的,这也是第三方方案出现的原因。3.0开始,官方推出了去中心化的分布式方案。集群中包含16384个散列槽,每个节点负责其中一部分。
先看下拓扑图:
每个节点打开两个tcp连接,一个负责给客户端提供服务,一个负责节点间通信。
此刻要说说cap了:consistency(一致性)、availability(可用性)、partitiontolerance(分区容错性)。对分布式系统而言,cap必须牺牲一者。rediscluster的设计目标主要是高性能、高可用和高扩展,只好抛弃一部分数据一致性。
数据一致性:由于rediscluster使用异步复制,在某些情况下如master宕机但未同步至slave,可能会导致丢失写入。在绝对需要支持同步写入时,可通过wait命令实现,可使得丢失写入的可能性大大降低。
可用性:当集群中一部分节点故障后,集群整体能响应客户端读写请求。
节点间定时互ping,当超过一半master判定某节点失败,则标记为fail,且会向集群广播节点下线的消息。如下线节点是带有槽的主节点,则要从它的从节点选出一个替换。
高性能和拓展:操作某个key时,不会先找到节点再处理,而是直接直接重定向到该节点,同时相较代理分片也少了proxy的连接损耗。
但是在进行multiplekey操作时需要keys位于同一个slot上,需要使用hashtags,使用{}强制将某些key映射到每个slot,以便进行multiple。
在拓展方面,rediscluster最大支持线性拓展1000个节点,将新节点加入集群后可以通过命令指定和平均的从已有节点分配slot。
4.缓存常见问题
以上介绍了简单介绍了常见缓存系统,并具体列出了基于redis的集群方案。下面谈一谈缓存系统常见的问题。
如下图所示,列出七个常见问题。
4.1.缓存穿透
指访问不存在的数据,从而绕过缓存,直接请求到了数据源,当请求过多,就会对db造成压力。
空key:指对于不存在的数据也将key存空值入缓存系统,这样下次访问也会得到返回。但只适用于空数据key有限、key重复请求概率高,如果量大且不重复,就会造成很多无用key的创建。
布隆过滤器:布隆过滤器是一个很长的二进制向量和一系列随机映射函数。可用于检索一个元素是否在一个集合中加一层对空值的过滤器,空间和时间效率都很高。但由于hash产生的碰撞可能存在误判,以及因不存储key导致的无法删除。适用于空数据key各不同、重复请求概率低。
4.2.缓存击穿
缓存击穿实际是缓存雪崩的一个特例。指当某些热点key过期时,就会有大量的请求击穿到db。
互斥锁:在缓存失效的时候,不立即loaddb,可以先用如setnx等命令去set一个mutexkey,当操作返回成功时,说明拿到锁,此刻该线程进行loaddb的操作并更新缓存;否则未拿到锁就(可休眠一段)重试get缓存的方法。但要注意死锁风险。
不过期
这里的不过期有两个概念,一个指未设过期时间,那是真的不过期,那没事了。
另一个是指通过业务逻辑,将key的过期时间进行存储,请求是判断是否小于值,是则后台异步更新。
4.3.缓存雪崩
同一时刻大量缓存失效(故障),请求到了db。
随机时间:在设置过期时间时,可以在基础时间上+一个随机的时间,等于实现了分批过期。
后台更新:将更新失效的工作交给后台定时线程。
限流+本地缓存:如ehcache本地缓存+hystrix限流。
双缓存:类似于设置主从缓存,从key不过期。
4.4.缓存更新与一致性
如果保证数据一致性。列出四种更新策略:
cacheaside:最常用的。失效时回源取数据,更新;命中时,返回缓存数据;更新时先数据源更新,再更新缓存。
writeback:更新数据时,只更新缓存,不更新数据源。缓存异步批量更新数据库。
read/writethrough
writethrough:当有数据更新时,如未命中缓存,直接更新数据库,并返回。如命中缓存,则更新缓存,再由cache自己更新数据库。
readthrough:更新数据源由缓存系统操作,读取数据时如缓存失效,则取回源数据更新缓存。
4.5.热点数据
对于热点数据的处理方法。
拆分复杂结构:如二级数据结构,进行拆分,这样热点key就被拆为若干个的key分布到不同节点。
迁移热点:对于rediscluster而言可以将热点key所在的slot单独迁移到一个节点,降低其他节点压力。
多副本:复制多份缓存副本,将请求分散到多个节点上,减轻单台缓存服务器压力,适合多读少写。
4.6.缓存预热
指可以将某些的缓存数据提前加载到缓存系统,提前避免在如热点数据大量请求到库。
4.7.缓存降级
指当访问量剧增、服务出现问题或非核心服务影响到核心流程的性能时,仍需保证主服务可用。可根据一些关键数据自动降级,也可配置开关人工降级。
5.rediscluster使用
对于rediscluster环境的搭建和基础使用非常简单。
无论基于何种方式,只要搭建好n台redis服务并保证各服务间可以互相通讯后,任意进入一个redis服务键入:
redis-cli--clustercreateip1:port1ip2:port2ip3:port3ip4:port4ip5:port5ip6:port6。。。--cluster-replicas1即可。之后可以使用clusternode和clusterinfo命令查看集群、节点信息。
而对于广大java开发,springdataredis从1.7起即支持rediscluster,只需配置master节点地址(和密码)。
spring.redis.cluster.nodes=ip1:port1,ip2:port2,ip3:port3
加入依赖
compile(“org.springframework.boot:spring-boot-starter-data-redis”)即可通过redistemplate使用。
6.总结
本文从缓存系统的选择出发,基于redis介绍了几种集群方案并重点说明了rediscluster方案。之后列出缓存系统常见问题及常见解决方案,最后对使用做了简单说明。
当然,如何去落地,如何解决这些问题还需要根据实际场景具体分析和处理。
通俗易懂的IPv6知识介绍
让义肢能够不断学习 才能真正让残疾人的世界变得更加美好
亿光去年获利稳定成长 今年重点产品将包括MiniLED及UV系列新品等
红外成像跟踪系统的EMC探讨
输电线路弧垂变化的原因及弧垂在线监测装置的工作原理
Redis集群缓存方案,缓存常见问题盘点
小米手机在墨西哥为何被限制使用双卡?
DC/DC升压模式转换器LT3598的性能特点及应用范围
ThinkPadX1Carbon2017评测 当下不可多得的优质高端商务本
高帧频中红外单光子上转换光谱仪研究进展
超声波电子捕鱼器电路图
“银发经济”红利凸显,适老化网关打开科技养老新蓝海
基于Modbus RTU通讯协议和S7 400 PLC实现原油输送站控系统的设计
马化腾阐述腾讯全新定位:一个目标,三个角色,五个领域,七种工具!
谷歌想说服人们放弃微软Chromium版Edge
格雷希尔G15系列自动化管内径密封快速密封连接器(铝合金版本)
射频无源器件的设计与对无线通信造成影响的原因
9大厂商联手推快应用,对抗小程序
关于无线充电的故事告诉你,为什么iPhone 8/iPhone X无线充电很鸡肋
一家使用AI进行皮肤癌筛查的初创公司,在A轮融资中筹集了400万英镑