分布式缓存基本原理
一、简述
在微服务架构下,一般需要一个分布式缓存系统来实现跨服务的缓存功能。缓存之间需要数据备份的功能,节点出现故障后,能保证用户的请求转发到其他备份节点来保证业务的正常运行。
二、Ehcache简述
Ehcache是一个用Java实现的使用简单,高速,实现线程安全的缓存管理类库,ehcache提供了用内存、磁盘文件存储,以及分布式存储方式等多种灵活的cache管理方案。
-
原理:内部采用多线程实现,采用了LinkHashMap存储元素,支持数据持久化到物理硬盘。
-
特点:快速、轻量、可伸缩、操作灵活、支持多种淘汰算法、支持持久化。
-
架构:如下图:
Replication:存储缓存副本
In-Process API:封装操作缓存数据的API
Core :管理缓存的CacheManager等
NetWork APIs:提供RESTful API等Web API接口 -
存储方式:堆存储(速度快)、堆外存储(不受GC限制)和磁盘存储(持久化方式)
三、Redis原理及应用
开源的内存中的数据结构存储系统,支持多种类型的数据结构,可用作内存数据库、缓存和消息中间件。
-
数据类型
- String:Setnx(不存在则设置,否则不处理)、Mset(批量设置)、Mget(批量获取)
- Hash:Hmset(批量设置)
- List:按照插入顺序排序
- Set:String类型的无序集合,集合通过散列表实现
- ZSet:每个元素会关联一个double类型的分数
- Bitmap:操作二进制位记录数据
- HyperLogLog
- Geospatial
-
Redis管道(批量发、批量收)
Redis基于请求/相应的TCP服务。客户端发送一个请求后,需要监听Socket的返回,监听过程一直阻塞。在分布式环境下,Redis的性能瓶颈主要在网络延迟上。Redis的管道技术指在服务端未响应时,客户端可以继续向服务端发送请求,最后一次性读取所有服务端的相应
Springboot中开启Pipeline如下:
新建RedisCallback对象并覆写doInRedis();在doInRedis()中通过connection.openPipeline()开启pipeline操作。RedisConnection connection; connection.openPipeline(); for(...){ ... connection.set(xxx,xxx); }
-
Redis的事务
执行流程如下:- 事务开启:client执行Multi命令
- 提交请求:client提交命令到事务
- 任务入队列:Redis将客户端请求放入事务队列中等待执行
- 入队列状态反馈:服务器返回QURUD,表明命令已放入事务队列
- 执行命令:通过Exec执行
- 事务执行错误:某条命令执行错误,其他命令会继续执行,不回滚。Watch可以监控
- 执行结果反馈:服务器给客户端反馈
-
Redis的发布、订阅
发布订阅是一种消息通信模式,发送者(Pub)向频道(Channel)发送消息,订阅者(Sub)接受消息
Redis客户端可以订阅多个频道 -
Redis集群数据复制的原理
Redis提供主从复制功能,过程如下:
-
Redis的持久化——RDB和AOF
- RDB:在指定时间间隔内对数据进行快照存储(.rdb快照文件)
- 子进程完成持久化工作,最大化性能
- 恢复大数据集比AOF快
- AOF:记录对服务器的每次写操作,在Redis重启时执行这些命令恢复数据
- 可使用不同的fsync策略将操作追加命令到文件中
- 日志格式的文件,易读
- RDB:在指定时间间隔内对数据进行快照存储(.rdb快照文件)
-
Redis集群模式及工作原理简述
三种模式——主从、哨兵、集群
- 主从模式:写请求到主数据库,主数据库将数据同步到从数据库中,从数据库主要用于执行读操作缓解系统的压力。从库还能拥有自己的从库。
- 哨兵模式:主从模式上增加了哨兵角色,用来监控集群的运行状态。通过发送命令让Redis服务器返回其运行状态,同时当Master宕机时,自动将Slave切换成Master,通过发布、订阅模式通知其他节点修改配置。
- 集群模式:实现了在多个Redis接地南之间进行数据分片和数据复制。能方便对Redis集群进行横向扩展,提高集群吞吐量。一部分节点失效时,Redis仍可对外提供服务,提高了集群的可用性。Redis集群遵循的原则如下:
- 内部使用PING-PONG机制
- 半数节点检测到某节点Fail,将该节点设置为Fail
- 客户端与Redis节点直连
- Redis-Cluster把所有的物理节点映射到16384个Slot上,每个Cluster负责维护分配到自己的Slot上的数据。在设置K-V时,Redis使用CRC16算法算出一个结果,把结果对16384取余,根据结果将数据存放到对应的节点中。这里涉及到Redis与Slot的映射方式,为了集群扩容与缩容实现起来更灵活,不得不提到一致性哈希。