服务器缓存系统

WEB系统中各参与者均可以进行缓存。数据库缓存,应用服务器缓存,Web服务器缓存,客户端浏览器缓存。php

 

java缓存级别:java

堆缓存python

堆外缓存mysql

磁盘缓存linux

分布式缓存nginx

 

典型java服务器端缓存系统:redis

一、接入nginx负载均衡到应用nginx。算法

二、应用nginx读取本地缓存(Nginx Proxy Cache或者Local Redis缓存)。若是命中,则直接返回。后续步骤中也是相似再也不赘述。sql

三、读取从redis服务器缓存。OpenResty的lua-resty-redis模块可使Nginx具备了直接读取redis缓存的能力,不占用tomcat的线程。数据库

三、回源到Tomcat集群。

四、Tomcat应用中,读取本地缓存。

六、回源到数据库集群。

七、将数据库返回的数据以异步方式写到主redis服务器。

 

有缓存时的查询流程:

应用服务器查询缓存。若是查到缓存服务器,则使用。若是没有查到缓存,则查询数据库。数据库返回结果后,应用服务器写缓存服务器,内容为key-value对。

 

缓存使用模式:

Cache-Aside:查不到缓存时,由业务代码回源SoR(source of record)

Cache-As-SoR:全部操做都是对cache进行,Cache进行SoR回源。

 

缓存淘汰or更新

淘汰缓存只是增长了一次cache miss。更新缓存虽然避免了cache miss,可是成本更高。因此一般淘汰缓存而不是更新。

 

数据库和缓存的一致性:

方式1:先更新数据库,而后同步淘汰缓存。优势:数据不一致性时间短。缺点:请求处理时间长。例如:使用mysql memcached UDF(用户自定义函数)和mysql触发器在更新mysql数据库的时候,触发淘汰cache。这样能够减小应用程序的逻辑。也能够保证事务的完整性。

方式2:先更新数据库,而后异步淘汰缓存。优势:请求处理时间短。缺点:数据不一致时间长。例如:可使用canal,模拟mysql slave和master的同步机制,监控mysql binlog来触发redis缓存的淘汰。

 

清除缓存

基于时间清除缓存:TTL和TTI(Time to Idle)

缓存满的含义:缓存超过设置的存储空间或者超过设置的条目数。

缓存满了,使用LRU机制驱逐老的缓存。热点缓存,要多存储几份,也能够在应用系统中进行几秒钟的本地缓存,从而下降远程缓存系统的压力。

除了LRU还有FIFO和LFU(Least Frequently used)

 

缓存相关问题:

缓存穿透:查询不存在的id,每次都会访问DB。若是id不存在,则内容设置为null,而且设置缓存的失效时间。

缓存雪崩:缓存集中过时失效(好比双11活动在0点开始,1点缓存集中失效)。缓存失效时间加一个随机因子,防止同时失效。能够在缓存失效前,主动通知后台线程更新缓存。

缓存击穿:一个key很是热点(爆款产品),这个key失效瞬间,致使大量数据库请求。对一个key只容许一个线程查询数据库和写缓存,其余线程等待。

缓存预热:缓存预热就是系统上线后,提早将相关的热点数据加载到缓存系统。避免在用户请求的时候,再查询数据库。

 

Redis:

redis是数据结构服务器,因此重点就是它支持的数据结构。使用命令来操做数据结构。最经常使用的命令是set()和get()。

Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用做数据库、高速缓存和消息队列。Key-Value中值(value)能够是字符串、列表、集合、有序集合、哈希、位图、hyperloglog(用于快速计算基数(一个数据集中不一样元素的数目))、流等数据类型。内置Lua脚本、LRU机制、事务以及不一样级别磁盘持久化功能。Redis支持master-slave模式的数据备份。能够经过Redis Sentinel(哨兵)提供高可用功能,发现主服务器崩溃后,自动选举新的主服务器,而且通知应用服务器。也能够经过Redis Cluster提供集群功能。

Redis使用ANSI C语言编写,提供多种语言的API,包括:c、C++、C#、php、java、python、go等语言。

Redis的全部操做都是原子性的,同时Redis还支持对几个操做合并后的原子性执行。

Redis支持 publish/subscribe模式,因此能够用做消息队列。

Redis 支持管道技术。容许服务端未响应时,客户端继续向服务端发送其它请求,并最终一次性读取全部服务端的响应。这提升了性能。

 

Twemproxy能够做为redis的代理。这样能够减小和后台缓存服务器的链接数。也能够用于实现redis集群。Twemproxy支持多种hash算法。支持失败节点自动删除。后端sharding(分片)逻辑对业务透明。

Redis集群也能够不使用Twemproxy,直接使用redis-cluster特性。Redis-Cluster采用无中心结构。健壮性更高。

数据按照hash slot存储分布在多个节点。

每一个节点保存整个集群状态,每一个节点(包括slave节点)都和其余全部节点链接。

每一个主节点有若干个slave节点。实现故障自动failover,节点之间经过gossip协议交换状态信息,用投票机制完成Slave到Master的角色提高。这相似于简化版的OSPF DR选举。可是又不一样,从节点发现主节点down了,从节点会广播request消息,要求成为主节点,其它从节点会若是赞成则返回ack,若是选票过半,则当选。gossip协议用于P2P网络中,传播消息的方式相似于OSPF的flood机制。

可扩展性,可线性扩展到 1000 个节点,节点可动态添加或删除。

高可用性,部分节点不可用时,集群仍可用。

应用服务器能够访问任何一个主节点,若是数据不在这个主节点上,它会返回一个moved重定向消息,告诉应用服务器应该访问哪一个主节点。可使用JedisPool,它将cluster slots的结果保存在本地,分配请求。

 

主从同步:

Redis全量复制一般发生在slave初始化阶段。以后就是增量赋值。

全量复制时,主服务器收到从服务器的SYNC命令后会生成RDB(Redis DataBase)快照文件。同时在缓冲区中记录此后执行的命令。将RDB文件发送给slave以后,还要将缓冲区中的命令发送给slave。以后主服务器执行写命令时就会向从服务器发送相同的写命令。

这和ospf很相似。可是ospf显然更先进,它会比较双方的LSDB,只请求缺失的部分。

主从同步还可使用AOF的方式,它的基本原理是从服务器回放主服务器执行过的命令。

 

redis cluster集群中经过消息来进行通讯。消息共有如下5种。

meet消息:加入到集群中。

ping消息:检测目标节点是否处于在线状态。

pong消息:收到到meet消息或者ping消息后,会回复pong消息。另外,pong消息也能够用于主动更新,例如故障转移后,新的主节点会向集群中发送pong消息,用于告知它已经升级为主节点。

fail消息:fail消息用于通知某个节点掉线了。例如节点A认为节点B已下线(B一段时间内都没有回复pong消息),节点A会向集群中发送一条fail消息,接收到这条消息的节点会将节点B标记为疑似下线。当大于等于半数的节点认为B下线了,这个节点就被标记为下线。

 

Redis vs Memcache

有持久化需求、对数据结构要求高、对处理有高级要求的应用,选择redis。简单的key/value存储,选择memcache。Redis只支持linux。Memcache支持windows、linux。

Redis支持简单的事务,只是一次性按顺序执行多条命令。可是不支持回滚,即有命令出错,也会继续执行。Memcache不支持事务。

Redis是单线程的。Memcache是多线程的。

Redis没有本身的内存管理模块。Memcache有本身的内存管理模块,内存分配效率更高。