分布式
分布式理论体系
分布式设计策略
- 如何检测你还活着 (心跳检测)
- 如何保证高可用(主备模式、互备模式、集群模式)
- 容错机制
- 重试机制
- 负载均衡
分布式系统设计实践
- 全局ID生成
- UUID
- ID生成表模式
- Snowflake
- 结合缓存方案
- 哈希取模分配
- 数据分布方式,哈希函数计算求余, 余数作为数据的服务器索引编号处理。
- 路由表
- 一般需要全局计算的节点。(比如用户抽奖,预算进行拆分到不同逻辑数据库,预算使用完便不在进行路由)
- 一致性哈希
- 主要解决单调性和分散性的问题。哈希的结果应能保证原有已分配的内容可以被映射到原有的缓冲中去,避免在节点增减的时候不能命中。
- 数据拆分
- cobar(阿里巴巴开源分布式数据库中间件)
java的引用
- 强引用
- 垃圾回收器不会回收
- 软引用
- 内存空间足够,不会回收。内存空间不足,就会回收这些对象。
- 弱引用
- 弱引用拥有更短的生命周期,在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间是否足够,都会回收它的内存
- 虚引用
- 在任何时候都有可能被内存回收。
EhCache和Cuava Cache
EhCache
Ecache 缓存数据过期策略
1、FIFO:根据数组的写入时间,数据先进先出。
2、LFU:最少被使用,缓存的元素有一个hit属性,hit值最小的将会被清出缓存。
3、LRU:最近最少被使用
Ehcache使用缓存
1、CacheMannager 创建。
2、将数据存放到缓存中。Element、Cache类。
3、关闭缓存CacheMannager.shutdown() 关闭缓存。
spring使用Ehcache缓存
1、@Cacheable可以使用缓存
2、@CachePut 缓存方法的执行结果,还会真实的执行方法。
3、@CachEvict 针对方法配置,能够根据一定的条件对缓存进行清空。
4、@CacheConfig 类级别的注解,主要是共享缓存的名称。
EhCache集群
1、JGroup模式
2、Terracotta
3、RMI组播方式:缓存改变时,Ehcache会组播IP地址和端口号发送RMI UDP组播包。
4、JMS消息方式:核心是消息队列。
5、Cache Server模式:缓存服务器集群模式支持RESTful 和SOAP
6、配置集群:服务提供者、服务监听、事件监听器。
Cuava Cache
适用场景: 愿意消耗一些本地内存空间来提升速度,或更新锁定。
全内存的本地缓存实现,提供了线程安全机制
Guava Cache创建方式
1、CacheLoader
2、Callable callback
Guava 使用缓存需要先声明一个CacheBuilder对象,并设置缓存的相关参数,调用build方法获取一个Cache接口的实例。
Callable方式:如果有缓存则返回,否则(进行缓存设置)读取、缓存、然后返回。
缓存数据删除
1、被动删除
1、基于数据大小删除 (记录数)CacheBuilder.maximumSize(size);
2、基于过期时间删除
expireAfterAccess:某个key最后一次访问过后,再隔多长时间后删除。
expireAfterWrite:某个key被创建后,再隔多长时间后删除
3、基于引用的删除
2、主动删除
1、单独删除 Cache.incvalidate(key)
2、批量删除 Cache.invalidateAll(key)
3、删除所有数据 Cache.invalidateAll()
并发场景下使用
对同一个key,只让一个请求去源中请求读取数据,其他请求阻塞等待结果。通过refreshAfterWriter定时刷新数据的配置项。
Mwncached集中式缓存
1、标准命令结构 command <key> <flags> <expiration time> <bytes> <value>,常用命令set、get、add、replace、addend、prepend。
2、特征:
1、协议简单: 文本协议或二进制协议
2、基于libevent的事件处理
3、内置内存存储方式
4、Memcached客户端分布式,服务端没有分布式功能,各个实例之间不会相互通信共享信息,分布式主要是通过客户端实现的。
3、Memcached的问题
1、无法备份,重启无法恢复,可通过持久化解决MencachedDB
2、无法查询
3、没有提供内置的安全机制
4、单点故障
4、Memcached内存存储
1、Slab Allocation机制
1、Page:分配给Slab的内存空间 默认1MB
2、Chunk:用于缓存记录的内存空间 默认growth factor:1.25
3、Slab class:特定大小的chunk组
2、简单来说:
Memcached根据收到的数据的大小,选择最合适数据大小的Slab,Memcached中保存着Slab内空闲的Cehunk的列表,根据该列表选择Chunk,然后将数据缓存于其中。
3、使用Growth Factor进行调优
4、Item是我们要保存的数据
完整长度:key(键)+nkey(键长)+flags(用户定义的flag)+nbytes(值长,包括\r\n)+suffix(后缀)+nsuffix(后缀长)
5、典型问题解析
1、容量问题 、服务高可用、扩展问题
2、过期机制
1、Lazy Expiration (get 查看记录的时间戳)
2、LRU
3、哈希算法
4、热点问题(巨热点数据发布到所有服务器上)
5、缓存与数据库的更新问题(更新的一致性问题)
6、别把缓存当存储()
7、CAS解决原子性操作的问题。
6、Memcached客户端分析
1、客户端对比:如下图
Redis集群
1、配置的一致性
1、clusterState 记录了从集群中某个节点的视角看来的集群配置状态。
2、currentEpoch 表示整个集群中的最大版本号,集群信息没变更一次,该版本号都会自增以保证每个信息的版本号唯一。
3、nodes 是一个列表,包含了本节点所知的集群所有节点的信息,其中也包含本节点自身。
4、clusterNode 记录了每个节点的信息。
2、数据分片(slot)
1、集群将所有的数据划分为16384个分片。
2、客户端的路由 (访问的key不在对应Redis节点的slots中,Redis返回给client一个moved命令,告知其正确的路由信息)
1、ask命令 :本条操作重定向到新节点
2、moved命令:会更新client数据分布,后续相同的slot操作会路由到新接点。
3、分片的迁移
1、节点和分片的对应关系需要发生变更(新的节点作为master加入、某个节点分组需要下线、负载不均需要调整slot分布)
2、分片迁移的触发和过程控制由外部系统完成。Redis Cluster只提供迁移过程需要的原语供外部系统调用。
1、节点迁移状态设置:迁移前标记源/目标源。
2、key迁移的原子化命令:迁移的具体步骤。
4、failover(故障转移)
1、failover的状态变迁:故障发现、故障确认、slave选举、集群结构变更
5、可用性和性能:
1、Redis Cluster的读写分离
2、master单点保护
参考书籍**《深入分布式缓存》**