A. 静态资源常用的一种缓存方式
http缓存分为强缓存和协商缓存。
强缓存并不会请求服务器,同时响应码会返回200。比如使用的配置cache-control:max-age=1200
在项目中缓存图片等静态资源常用的是协商缓存。
在第一次请求静态资源的时候,服务器会根据资源内容生成etag, 在响应头里返回给浏览器,在下次请求的时候浏览器会在头部配置If-None-Match,携带etag来向服务器询问资源是否发生改变。若是没有发生改变会返回304,这样浏览器就不会从服务器重新获取资源而是直接使用本地缓存。采用etag可以解决文件名没有发生变化但是文件内容被修改的问题。
通常会跟cache-control: no-cache 在一起配合使用。no-cache是指浏览器可以缓存响应,但是必须要向原始服务器提交验证请求。
参考:
https://www.imperva.com/learn/performance/cache-control/
https://blog.csdn.net/aimeimeiTS/article/details/105731709
https://www.zoo.team/article/http-cache
https://imweb.io/topic/5795dcb6fb312541492eda8c
https://aotu.io/notes/2016/09/22/http-caching/index.html
B. 高性能高并发网站架构,教你搭建Redis5缓存集群
一、Redis集群介绍
Redis真的是一个优秀的技术,它是一种key-value形式的Nosql内存数据库,由ANSI C编写,遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 Redis最大的特性是它会将所有数据都放在内存中,所以读写速度性能非常好。Redis是基于内存进行操作的,性能较高,可以很好的在一定程度上解决网站一瞬间的并发量,例如商品抢购秒杀等活动。
网站承受高并发访问压力的同时,还需要从海量数据中查询出满足条件的数据,需要快速响应,前端发送请求、后端和mysql数据库交互,进行sql查询操作,读写比较慢,这时候引入Redis ,把从mysql 的数据缓存到Redis 中,下次读取时候性能就会提高;当然,它也支持将内存中的数据以快照和日志的形式持久化到硬盘,这样即使在断电、机器故障等异常情况发生时数据也不会丢失,Redis能从硬盘中恢复快照数据到内存中。
Redis 发布了稳定版本的 5.0 版本,放弃 Ruby的集群方式,改用 C语言编写的 redis-cli的方式,是集群的构建方式复杂度大大降低。Redis-Cluster集群采用无中心结构,每个节点保存数据和整个集群状态,每个节点都和其他所有节点连接。
为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉。
redis-cluster投票:容错,投票过程是集群中所有master参与,如果半数以上master节点与master节点通信超过(cluster-node-timeout),认为当前master节点挂掉。
集群中至少应该有奇数个节点,所以至少有三个节点,每个节点至少有一个备份节点,所以下面使用6节点(主节点、备份节点由redis-cluster集群确定)。6个节点分布在一台机器上,采用三主三从的模式。实际应用中,最好用多台机器,比如说6个节点分布到3台机器上,redis在建立集群时为自动的将主从节点进行不同机器的分配。
二、单机redis模式
下载源码redis5.0并解压编译
wget http://download.redis.io/releases/redis-5.0.0.tar.gz
tar xzf redis-5.0.0.tar.gz
cd redis-5.0.0
make
redis前端启动需要改成后台启动.
修改redis.conf文件,将daemonize no -> daemonize yes
vim redis.conf
启动redis
/www/server/redis/src/redis-server /www/server/redis/redis.conf
查看redis是否在运行
ps aux|grep redis
现在是单机redis模式完成。
三、redis集群模式:
1.创建6个Redis配置文件
cd /usr/local/
mkdir redis_cluster //创建集群目录
cd redis_cluster
mkdir 7000 7001 7002 7003 7004 7005//分别代表6个节点
其对应端口 7000 7001 7002 70037004 7005
2.复制配置文件到各个目录
cp /www/server/redis/redis.conf /usr/local/redis_cluster/7000/
cp /www/server/redis/redis.conf /usr/local/redis_cluster/7001/
cp /www/server/redis/redis.conf /usr/local/redis_cluster/7002/
cp /www/server/redis/redis.conf /usr/local/redis_cluster/7003/
cp /www/server/redis/redis.conf /usr/local/redis_cluster/7004/
cp /www/server/redis/redis.conf /usr/local/redis_cluster/7005/
3.分别修改配置文件
vim /usr/local/redis_cluster/7000/redis.conf
vim /usr/local/redis_cluster/7001/redis.conf
vim /usr/local/redis_cluster/7002/redis.conf
vim /usr/local/redis_cluster/7003/redis.conf
vim /usr/local/redis_cluster/7004/redis.conf
vim /usr/local/redis_cluster/7005/redis.conf
如下
port 7000 #端口
cluster-enabled yes #启用集群模式
cluster-config-file nodes_7000.conf #集群的配置 配置文件首次启动自动生成
cluster-node-timeout 5000 #超时时间 5秒
appendonly yes #aof日志开启 它会每次写操作都记录一条日志
daemonize yes #后台运行
protected-mode no #非保护模式
pidfile /var/run/redis_7000.pid
//下面可以不写
#若设置密码,master和slave需同时配置下面两个参数:
masterauth "jijiji" #连接master的密码
requirepass "jijiji" #自己的密码
cluster-config-file,port,pidfile对应数字
4.启动节点
cd /www/server/redis/src/
./redis-server /usr/local/redis_cluster/7000/redis.conf
./redis-server /usr/local/redis_cluster/7001/redis.conf
./redis-server /usr/local/redis_cluster/7002/redis.conf
./redis-server /usr/local/redis_cluster/7003/redis.conf
./redis-server /usr/local/redis_cluster/7004/redis.conf
./redis-server /usr/local/redis_cluster/7005/redis.conf
查看redis运行
ps aux|grep redis
5.启动集群
/www/server/redis/src/redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1
这里使用的命令是create,因为我们要创建一个新的集群。 该选项--cluster-replicas 1意味着我们希望每个创建的主服务器都有一个从服。
输入yes
至此,Reids5 集群搭建完成。
6.检查Reids5集群状态
可以执行redis-cli --cluster check host:port检查集群状态slots详细分配。
redis-cli --cluster info 127.0.0.1:7000
7.停止Reids5集群
(1).因为Redis可以妥善处理SIGTERM信号,所以直接kill -9也是可以的,可以同时kill多个,然后再依次启动。
kill -9 PID PID PID
(2).redis5 提供了关闭集群的工具,修改文件: /www/server/redis/utils/create-cluster/create-cluster
端口PROT设置为6999,NODES为6,工具会生成 7000-7005 六个节点 用于操作。
修改后,执行如下命令关闭集群:
/www/server/redis/utils/create-cluster/create-cluster stop
重新启动集群:
/www/server/redis/utils/create-cluster/create-cluster start
8.帮助信息
执行redis-cli --cluster help,查看更多帮助信息
redis-cli --cluster help
吉海波
C. 缓存是什么 深入解析网页缓存机制
缓存是指在计算机系统中,将数据暂时存储在高速缓存中,以提高数据访问速度的一种技术。在网页浏览器中,也存在着网页缓存机制,它可以使用户在访问同一网页时,不必每次都从服务器重新获取数据,而是从本地缓存中读取数据,从而提高网页的访问速度。
缓存是指在计算机系统中,将数据暂时存储在高速缓存中,以提高数据访问速度的一种技术。在网页浏览器中,也存在着网页缓存机制,它可以使用户在访问同一网页时,不必每次都从服务器重新获取数据,而是从本地缓存中读取数据,从而提高网页的访问速度。
协商缓存是指在第一次访问网页时,服务器返回的响应头中包含了缓存标识,浏览器会将该网页缓存在本地,并在下次访问时将该缓存标识发送给服务器,询问服务器该网页是否有更新。如果服务器返回的响应头中包含了“304 Not Modified”配咐的状培森纯态码,则表示该网页没有更新,浏览器会直接从本地缓存中读取数据,否则就从服务器上重新获取数据。
网页缓存是指将已经访问过的网页内容保存在用户的本地存储中,以便下次访问时可以更快速地加载页面。当用户访问一个网页时,浏览器会首先查看本地缓存中是否存在该网页的春枝副本,如果存在,则直接从缓存中读取,否则就从服务器上重新获取数据。
强制缓存是指在第一次访问网页时,服务器返回的响应头中包含了缓存时间,浏览器会将该网页缓存在本地,并在缓存时间内不会向服务器发送请求。当缓存时间过期后,浏览器会再次向服务器发送请求,重新获取数据。
缓存是指在计算机系统中,将数据暂时存储在高速缓存中,以提高数据访问速度的一种技术。在网页浏览器中,也存在着网页缓存机制,它可以使用户在访问同一网页时,不必每次都从服务器重新获取数据,而是从本地缓存中读取数据,从而提高网页的访问速度。
D. 浏览器缓存原理简述
缓存文件存储方式有2种:内存和硬盘。为了提高文件读取速度,浏览器优先读内存中的缓存文件(如果存在的话)。
按照本地缓存阶段和协商缓存阶段分类:
缓存的策略由http消息头Cache-Control确定,以下为各个值对应的效果:
Cache-Control:public :所有内容都将被缓存(客户端和代理服务器都可缓存)
Cache-Control:private :所有内容只有客户端可以缓存
Cache-Control:no-cache :默认值。客户端缓存内容,但是是否使用缓存则需要经过协商缓存来验证决定
Cache-Control:no-store :所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存
Cache-Control:max-age=xxx (xxx is numeric) :缓存内容将在xxx秒后失效
HTTP1.0 的特性,标识该资源过期的时间点,它是一个绝对值,格林威治时间(Greenwich Mean Time, GMT),即在这个时间点之后,缓存的资源过期; 优先级:Cache-Control 优先级高于 Expires ,为了兼容,通常两个头部同时设置;浏览器默认行为:其实就算 Response Header 中没有设置 Cache-Control 和 Expires,浏览器仍然会缓存某些资源,这是浏览器的默认行为,是为了提升性能进行的优化,每个浏览器的行为可能不一致,有些浏览器甚至没有这样的优化。
Last-Modified (Response Header)与 If-Modified-Since (Request Header)是一对报文头,属于 http 1.0。
If-Modified-Since 是一个请求首部字段,并且只能用在 GET 或者 HEAD 请求中。Last-Modified 是一个响应首部字段,包含服务器认定的资源作出修改的日期及时间。当带着 If-Modified-Since 头访问服务器请求资源时,服务器会检查 Last-Modified,如果 Last-Modified 的时间早于或等于 If-Modified-Since 则会返回一个不带主体的 304 响应,否则将重新返回资源。
ETag 与 If-None-Match 是一对报文头,属于 http 1.1。
ETag 是一个响应首部字段,它是根据实体内容生成的一段 hash 字符串,标识资源的状态,由服务端产生。If-None-Match 是一个条件式的请求首部。如果请求资源时在请求首部加上这个字段,值为之前服务器端返回的资源上的 ETag,则当且仅当服务器上没有任何资源的 ETag 属性值与这个首部中列出的时候,服务器才会返回带有所请求资源实体的 200 响应,否则服务器会返回不带实体的 304 响应。
E. 如何理解redis+tomcat+nginx集群缓存
Nginx是一款轻量级兼备高性能的Http和反向代理服务器。
所谓反向代理就是指在用户发起访问请求,由代理服务器接收,然后将请求转发给正式服务器,并且将正式服务器处理完的数据返回给客户端,此时代理服务器就表现为一个服务器。
F. EhCache 分布式缓存/缓存集群
一 缓存系统简介 EhCache 是一个纯 Java 的进程内缓存框架 具有快速 精干等特点 是 Hibernate 中默认的 CacheProvider EhCache 应用架构图 下图是 EhCache 在应用程序中的位置
EhCache 的主要特性有 快速 精干 简单 多种缓存策略 缓存数据有两级 内存和磁盘 因此无需担心容量问题 缓存数据会在虚拟机重启的过程中写入磁盘 可以通过 RMI 可插入 API 等方式进行分布式缓存 具有缓存和缓存管理器的侦听接口 支持多缓存管理器实例 以及一个实例的多个缓存区域 提供 Hibernate 的缓存实现 由于 EhCache 是进程中的缓存系统 一旦将应用部署在集群环境中 每一个节点维护各自的缓存数据 当某个节点对缓存数据进行更新 这些更新的数据无法在其它节点 *** 享 这不仅会降低节点运行的效率 而且会导致数据不同步的情况发生 例如某个网站采用 A B 两个节点作为集群部署 当 A 节点的缓存更新后 而 B 节点缓存尚未更新就可能出现用户在浏览页面的时候 一会是更新后的数据 一会是尚未更新的数据 尽管我们也可以通过 Session Sticky 技术来将用户锁定在某个节点上 但对于一些交互性比较强或者是非 Web 方式的系统来说 Session Sticky 显然不太适合 所以就需要用到 EhCache 的集群解决方案 从 版本开始 Ehcache可以使用分布式的缓存了 EhCache 从 版本开始 支持五种集群方案 分别是 ? Terracotta ? RMI ? JMS ? JGroups ? EhCache Server 其中的三种最为常用集群方式 分别是 RMI JGroups 以及 EhCache Server 本文主要介绍RMI的方式 分布式这个特性是以plugin的方式实现的 Ehcache自带了一些默认的分布式缓存插件实现 这些插件可以满足大部分应用的需要 如果需要使用其他的插件那就需要自己开发了 开发者可以通过查看distribution包里的源代码及JavaDoc来实现它 尽管不是必须的 在使用分布式缓存时理解一些ehcahce的设计思想也是有帮助的 这可以参看分布式缓存设计的页面 以下的部分将展示如何让分布式插件同ehcache一起工作 下面列出的是一些分布式缓存中比较重要的方面 ? 你如何知道集群环境中的其他缓存? ? 分布式传送的消息是什么形式? ? 什么情况需要进行复制?增加(Puts) 更新(Updates)或是失效(Expiries)? ? 采用什么方式进行复制?同步还是异步方式? 为了安装分布式缓存 你需要配置一个PeerProvider 一个CacheManagerPeerListener 它们对于一个CacheManager来说是全局的 每个进行分布式操作的cache都要添加一个cacheEventListener来传送消息
二 集群缓存概念及其配置 正确的元素类型 只有可序列化的元素可以进行复制 一些操作 比如移除 只需要元素的键值而不用整个元素 在这样的操作中即使元素不是可序列化的但键值是可序列化的也可以被复制 成员发现(Peer Discovery) Ehcache进行集群的时候有一个cache组的概念 每个cache都是其他cache的一个peer 没有主cache的存在 刚才我们问了一个问题 你如何知道集群环境中的其他缓存?这个问题可以命名为成员发现(Peer Discovery) Ehcache提供了两种机制用来进行成员发现 就像一辆汽车 手动档和自动档 要使用一个内置的成员发现机制要在ehcache的配置文件中指定元素的class属性为 net sf ehcache distribution 自动的成员发现 自动的发现方式用TCP广播机制来确定和维持一个广播组 它只需要一个简单的配置可以自动的在组中添加和移除成员 在集群中也不需要什么优化服务器的知识 这是默认推荐的 成员每秒向群组发送一个 心跳 如果一个成员 秒种都没有发出信号它将被群组移除 如果一个新的成员发送了一个 心跳 它将被添加进群组 任何一个用这个配置安装了复制功能的cache都将被其他的成员发现并标识为可用状态 要设置自动的成员发现 需要指定ehcache配置文件中元素的properties属性 就像下面这样 peerDiscovery=automatic multicastGroupAddress=multicast address | multicast host name multicastGroupPort=port timeToLive= (timeToLive属性详见常见问题部分的描述) 示例 假设你在集群中有两台服务器 你希望同步sampleCache 和sampleCache 每台独立的服务器都要有这样的配置 配置server 和server <class= net sf ehcache distribution properties= peerDiscovery=automatic multicastGroupAddress= />multicastGroupPort= timeToLive= 手动进行成员发现 进行手动成员配置要知道每个监听器的IP地址和端口 成员不能在运行时动态地添加和移除 在技术上很难使用广播的情况下就可以手动成员发现 例如在集群的服务器之间有一个不能传送广播报文的路由器 你也可以用手动成员发现进行单向的数据复制 只让server 知道server 而server 不知道server 配置手动成员发现 需要指定ehcache配置文件中的properties属性 像下面这样 peerDiscovery=manual rmiUrls=//server:port/cacheName //server:port/cacheName … rmiUrls配置的是服务器cache peers的列表 注意不要重复配置 示例 假设你在集群中有两台服务器 你要同步sampleCache 和sampleCache 下面是每个服务器需要的配置 配置server <class= net sf ehcache distribution properties= peerDiscovery=manual />rmiUrls=//server : /sampleCache |//server : /sampleCache 配置server <class= net sf ehcache distribution properties= peerDiscovery=manual />rmiUrls=//server : /sampleCache |//server : /sampleCache 配置CacheManagerPeerListener 每个CacheManagerPeerListener监听从成员们发向当前CacheManager的消息 配置CacheManagerPeerListener需要指定一个 它以插件的机制实现 用来创建CacheManagerPeerListener 的属性有 class – 一个完整的工厂类名 properties – 只对这个工厂有意义的属性 使用逗号分隔 Ehcache有一个内置的基于RMI的分布系统 它的监听器是RMICacheManagerPeerListener 这个监听器可以用 RMI来配置 <class= net sf ehcache distribution RMI properties= hostName=localhost port= />socketTimeoutMillis= 有效的属性是 hostname (可选) – 运行监听器的服务器名称 标明了做为集群群组的成员的地址 同时也是你想要控制的从集群中接收消息的接口在CacheManager初始化的时候会检查hostname是否可用 如果hostName不可用 CacheManager将拒绝启动并抛出一个连接被拒绝的异常 如果指定 hostname将使用InetAddress getLocalHost() getHostAddress()来得到 警告 不要将localhost配置为本地地址 因为它在网络中不可见将会导致不能从远程服务器接收信息从而不能复制 在同一台机器上有多个CacheManager的时候 你应该只用localhost来配置 port – 监听器监听的端口 socketTimeoutMillis (可选) – Socket超时的时间 默认是 ms 当你socket同步缓存请求地址比较远 不是本地局域网 你可能需要把这个时间配置大些 不然很可能延时导致同步缓存失败 配置CacheReplicators 每个要进行同步的cache都需要设置一个用来向CacheManagerr的成员复制消息的缓存事件监听器 这个工作要通过为每个cache的配置增加一个cacheEventListenerFactory元素来完成 <! Sample cache named sampleCache ><cache name= sampleCache maxElementsInMemory= eternal= false timeToIdleSeconds= timeToLiveSeconds= overflowToDisk= false ><cacheEventListenerFactory class= net sf ehcache distribution RMICacheReplicatorFactory properties= replicateAsynchronously=true replicatePuts=true replicateUpdates=true replicateUpdatesViaCopy=false replicateRemovals=true /></cache>class – 使用net sf ehcache distribution RMICacheReplicatorFactory 这个工厂支持以下属性 replicatePuts=true | false – 当一个新元素增加到缓存中的时候是否要复制到其他的peers 默认是true replicateUpdates=true | false – 当一个已经在缓存中存在的元素被覆盖时是否要进行复制 默认是true replicateRemovals= true | false – 当元素移除的时候是否进行复制 默认是true replicateAsynchronously=true | false – 复制方式是异步的(指定为true时)还是同步的(指定为false时) 默认是true replicatePutsViaCopy=true | false – 当一个新增元素被拷贝到其他的cache中时是否进行复制指定为true时为复制 默认是true replicateUpdatesViaCopy=true | false – 当一个元素被拷贝到其他的cache中时是否进行复制(指定为true时为复制) 默认是true 你可以使用ehcache的默认行为从而减少配置的工作量 默认的行为是以异步的方式复制每件事 你可以像下面的例子一样减少RMICacheReplicatorFactory的属性配置 <! Sample cache named sampleCache All missing RMICacheReplicatorFactory properties default to true ><cache name= sampleCache maxElementsInMemory= eternal= true overflowToDisk= false memoryStoreEvictionPolicy= LFU ><cacheEventListenerFactory class= net sf ehcache distribution RMICacheReplicatorFactory /></cache> 常见的问题 Windows上的Tomcat 有一个Tomcat或者是JDK的bug 在tomcat启动时如果tomcat的安装路径中有空格的话 在启动时RMI监听器会失败 参见 bin/wa?A =ind &L=rmi users&P= 和 doc/faq howto bugs/l 由于在Windows上安装Tomcat默认是装在 Program Files 文件夹里的 所以这个问题经常发生 广播阻断 自动的peer discovery与广播息息相关 广播可能被路由阻拦 像Xen和VMWare这种虚拟化的技术也可以阻拦广播 如果这些都打开了 你可能还在要将你的网卡的相关配置打开 一个简单的办法可以告诉广播是否有效 那就是使用ehcache remote debugger来看 心跳 是否可用 广播传播的不够远或是传得太远 你可以通过设置badly misnamed time to live来控制广播传播的距离 用广播IP协议时 timeToLive的值指的是数据包可以传递的域或是范围 约定如下 是限制在同一个服务器 是限制在同一个子网 是限制在同一个网站 是限制在同一个region 是限制在同一个大洲 是不限制 译者按 上面这些资料翻译的不够准确 请读者自行寻找原文理解吧 在Java实现中默认值是 也就是在同一个子网中传播 改变timeToLive属性可以限制或是扩展传播的范围
三 RMI方式缓存集群/配置分布式缓存 RMI 是 Java 的一种远程方法调用技术 是一种点对点的基于 Java 对象的通讯方式 EhCache 从 版本开始就支持 RMI 方式的缓存集群 在集群环境中 EhCache 所有缓存对象的键和值都必须是可序列化的 也就是必须实现 java io Serializable 接口 这点在其它集群方式下也是需要遵守的 下图是 RMI 集群模式的结构图
采用 RMI 集群模式时 集群中的每个节点都是对等关系 并不存在主节点或者从节点的概念 因此节点间必须有一个机制能够互相认识对方 必须知道其它节点的信息 包括主机地址 端口号等 EhCache 提供两种节点的发现方式 手工配置和自动发现 手工配置方式要求在每个节点中配置其它所有节点的连接信息 一旦集群中的节点发生变化时 需要对缓存进行重新配置 由于 RMI 是 Java 中内置支持的技术 因此使用 RMI 集群模式时 无需引入其它的 Jar 包 EhCache 本身就带有支持 RMI 集群的功能 使用 RMI 集群模式需要在 ehcache xml 配置文件中定义 节点 分布式同步缓存要让这边的cache知道对方的cache 叫做Peer Discovery(成员发现) EHCache实现成员发现的方式有两种 手动查找 A 在ehcache xml中配置PeerDiscovery成员发现对象 Server 配置 配置本地hostName port是 分别监听 : 的mobileCache和 : 的mobileCache 注意这里的mobileCache是缓存的名称 分别对应着server server 的cache的配置 <?xml version= encoding= gbk ?><ehcache xmlns:xsi= instance xsi:noNamespaceSchemaLocation= ehcache xsd > <diskStore path= java io tmpdir /> <! 集群多台服务器中的缓存 这里是要同步一些服务器的缓存 server hostName: port: cacheName:mobileCache server hostName: port: cacheName:mobileCache server hostName: port: cacheName:mobileCache 注意 每台要同步缓存的服务器的RMI通信socket端口都不一样 在配置的时候注意设置 > <! server 的配置 > < class= net sf ehcache distribution properties= hostName=localhost port= socketTimeoutMillis= peerDiscovery=manual rmiUrls=// : /mobileCache|// : /mobileCache /></ehcache>以上注意元素出现的位置在diskStore下
同样在你的另外 台服务器上增加配置 Server 配置本地host port为 分别同步 : 的mobileCache和 : 的mobileCache <! server 的配置 >< class= net sf ehcache distribution properties= hostName=localhost port= socketTimeoutMillis= peerDiscovery=manual rmiUrls=// : /mobileCache|// : /mobileCache />Server 配置本地host port为 分别同步 : 的mobileCache缓存和 : 的mobileCache缓存 <! server 的配置 >< class= net sf ehcache distribution properties= hostName=localhost port= socketTimeoutMillis= peerDiscovery=manual rmiUrls=// : /mobileCache|// : /mobileCache />这样就在三台不同的服务器上配置了手动查找cache的PeerProvider成员发现的配置了 值得注意的是你在配置rmiUrls的时候要特别注意url不能重复出现 并且端口 地址都是对的 如果指定 hostname将使用InetAddress getLocalHost() getHostAddress()来得到 警告 不要将localhost配置为本地地址 因为它在网络中不可见将会导致不能从远程服务器接收信息从而不能复制 在同一台机器上有多个CacheManager的时候 你应该只用localhost来配置 B 下面配置缓存和缓存同步监听 需要在每台服务器中的ehcache xml文件中增加cache配置和cacheEventListenerFactory cacheLoaderFactory的配置 <defaultCache maxElementsInMemory= eternal= false timeToIdleSeconds= timeToLiveSeconds= overflowToDisk= false /><! 配置自定义缓存 maxElementsInMemory:缓存中允许创建的最大对象数 eternal:缓存中对象是否为永久的 如果是 超时设置将被忽略 对象从不过期 timeToIdleSeconds:缓存数据空闲的最大时间 也就是说如果有一个缓存有多久没有被访问就会被销毁 如果该值是 就意味着元素可以停顿无穷长的时间 timeToLiveSeconds:缓存数据存活的时间 缓存对象最大的的存活时间 超过这个时间就会被销毁 这只能在元素不是永久驻留时有效 如果该值是 就意味着元素可以停顿无穷长的时间 overflowToDisk:内存不足时 是否启用磁盘缓存 memoryStoreEvictionPolicy:缓存满了之后的淘汰算法 每一个小时更新一次缓存( 小时过期) ><cache name= mobileCache maxElementsInMemory= eternal= false overflowToDisk= true timeToIdleSeconds= timeToLiveSeconds= memoryStoreEvictionPolicy= LFU > <! RMI缓存分布同步查找 class使用net sf ehcache distribution RMICacheReplicatorFactory 这个工厂支持以下属性 replicatePuts=true | false – 当一个新元素增加到缓存中的时候是否要复制到其他的peers 默认是true replicateUpdates=true | false – 当一个已经在缓存中存在的元素被覆盖时是否要进行复制 默认是true replicateRemovals= true | false – 当元素移除的时候是否进行复制 默认是true replicateAsynchronously=true | false – 复制方式是异步的 指定为true时 还是同步的 指定为false时 默认是true replicatePutsViaCopy=true | false – 当一个新增元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true replicateUpdatesViaCopy=true | false – 当一个元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true = > <! 监听RMI同步缓存对象配置 注册相应的的缓存监听类 用于处理缓存事件 如put remove update 和expire > <cacheEventListenerFactory class= net sf ehcache distribution RMICacheReplicatorFactory properties= replicateAsynchronously=true /> replicatePuts=true replicateUpdates=true replicateUpdatesViaCopy=false replicateRemovals=true <! 用于在初始化缓存 以及自动设置 > <bootstrapCacheLoaderFactory class= net sf ehcache bootstrap BootstrapCacheLoaderFactory /></cache> C 这样就完成了 台服务器的配置 下面给出server 的完整的ehcache xml的配置 <?xml version= encoding= gbk ?><ehcache xmlns:xsi= instance xsi:noNamespaceSchemaLocation= ehcache xsd > <diskStore path= java io tmpdir /> <!集群多台服务器中的缓存 这里是要同步一些服务器的缓存 server hostName: port: cacheName:mobileCache server hostName: port: cacheName:mobileCache server hostName: port: cacheName:mobileCache 注意每台要同步缓存的服务器的RMI通信socket端口都不一样 在配置的时候注意设置 > <! server 的配置 > < class= net sf ehcache distribution properties= hostName=localhost port= socketTimeoutMillis= peerDiscovery=manual rmiUrls=// : /mobileCache|// : /mobileCache /> <defaultCache maxElementsInMemory= eternal= false timeToIdleSeconds= timeToLiveSeconds= overflowToDisk= false /> <! 配置自定义缓存 maxElementsInMemory:缓存中允许创建的最大对象数 eternal:缓存中对象是否为永久的 如果是 超时设置将被忽略 对象从不过期 timeToIdleSeconds:缓存数据空闲的最大时间 也就是说如果有一个缓存有多久没有被访问就会被销毁 如果该值是 就意味着元素可以停顿无穷长的时间 timeToLiveSeconds:缓存数据存活的时间 缓存对象最大的的存活时间 超过这个时间就会被销毁 这只能在元素不是永久驻留时有效 如果该值是 就意味着元素可以停顿无穷长的时间 overflowToDisk:内存不足时 是否启用磁盘缓存 memoryStoreEvictionPolicy:缓存满了之后的淘汰算法 每一个小时更新一次缓存( 小时过期) > <cache name= mobileCache maxElementsInMemory= eternal= false overflowToDisk= true timeToIdleSeconds= timeToLiveSeconds= memoryStoreEvictionPolicy= LFU > <! RMI缓存分布同步查找 class使用net sf ehcache distribution RMICacheReplicatorFactory 这个工厂支持以下属性 replicatePuts=true | false – 当一个新元素增加到缓存中的时候是否要复制到其他的peers 默认是true replicateUpdates=true | false – 当一个已经在缓存中存在的元素被覆盖时是否要进行复制 默认是true replicateRemovals= true | false – 当元素移除的时候是否进行复制 默认是true replicateAsynchronously=true | false – 复制方式是异步的 指定为true时 还是同步的 指定为false时 默认是true replicatePutsViaCopy=true | false – 当一个新增元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true replicateUpdatesViaCopy=true | false – 当一个元素被拷贝到其他的cache中时是否进行复制 指定为true时为复制 默认是true = > <! 监听RMI同步缓存对象配置 注册相应的的缓存监听类 用于处理缓存事件 如put remove update 和expire > <cacheEventListenerFactory class= net sf ehcache distribution RMICacheReplicatorFactory properties= replicateAsynchronously=true /> replicatePuts=true replicateUpdates=true replicateUpdatesViaCopy=false replicateRemovals=true <! 用于在初始化缓存 以及自动设置 > <bootstrapCacheLoaderFactory class= net sf ehcache bootstrap BootstrapCacheLoaderFactory /> </cache></ehcache> 自动发现 自动发现配置和手动查找的方式有一点不同 其他的地方都基本是一样的 同样在ehcache xml中增加配置 配置如下 <! 搜索某个网段上的缓存timeToLive 是限制在同一个服务器 是限制在同一个子网 是限制在同一个网站 是限制在同一个region 是限制在同一个大洲 是不限制 >< class= net sf ehcache distribution properties= peerDiscovery=automatic multicastGroupAddress= multicastGroupPort= timeToLive= /> lishixin/Article/program/Java/hx/201311/25706
G. 将缓存数据分配到集群的不同节点,分片规则使用什么算法
以每24小时作为一份时间(而非自然日),根据用户的配置有两种工作模式:带状模式中,用户仅定义开始日期时,从开始日期(含)开始,每份时间1个分片地无限增加下去;环状模式中,用户定义了开始日期和结束日期时,以结束日期(含)和开始日期(含)之间的时间份数作为分片总数(分片数量固定),以类似取模的方式路由到这些分片里。
1. DBLE 启动时,读取用户在 rule.xml 配置的 sBeginDate 来确定起始时间
2. 读取用户在 rule.xml 配置的 sPartionDay 来确定每个 MySQL 分片承载多少天内的数据
3. 读取用户在 rule.xml 配置的 dateFormat 来确定分片索引的日期格式
4. 在 DBLE 的运行过程中,用户访问使用这个算法的表时,WHERE 子句中的分片索引值(字符串),会被提取出来尝试转换成 Java 内部的时间类型
5. 然后求分片索引值与起始时间的差,除以 MySQL 分片承载的天数,确定所属分片
1. DBLE 启动时,读取用户在 rule.xml 配置的起始时间 sBeginDate、终止时间 sEndDate 和每个 MySQL 分片承载多少天数据 sPartionDay
2. 根据用户设置,建立起以 sBeginDate 开始,每 sPartionDay 天一个分片,直到 sEndDate 为止的一个环,把分片串联串联起来
3. 读取用户在 rule.xml 配置的 defaultNode
4. 在 DBLE 的运行过程中,用户访问使用这个算法的表时,WHERE 子句中的分片索引值(字符串),会被提取出来尝试转换成 Java 内部的日期类型
5. 然后求分片索引值与起始日期的差:如果分片索引值不早于 sBeginDate(哪怕晚于 sEndDate),就以 MySQL 分片承载的天数为模数,对分片索引值求模得到所属分片;如果分片索引值早于 sBeginDate,就会被放到 defaultNode 分片上
与MyCat的类似分片算法对比
中间件
DBLE
MyCat
分片算法种类 date 分区算法 按日期(天)分片
两种中间件的取模范围分片算法使用上无差别
开发注意点
【分片索引】1. 必须是字符串,而且 java.text.SimpleDateFormat 能基于用户指定的 dateFormat 来转换成 java.util.Date
【分片索引】2. 提供带状模式和环状模式两种模式
【分片索引】3. 带状模式以 sBeginDate(含)起,以 86400000 毫秒(24 小时整)为一份,每 sPartionDay 份为一个分片,理论上分片数量可以无限增长,但是出现 sBeginDate 之前的数据而且没有设定 defaultNode 的话,会路由失败(如果有 defaultNode,则路由至 defaultNode)
【分片索引】4. 环状模式以 86400000 毫秒(24 小时整)为一份,每 sPartionDay 份为一个分片,以 sBeginDate(含)到 sEndDate(含)的时间长度除以单个分片长度得到恒定的分片数量,但是出现 sBeginDate 之前的数据而且没有设定 defaultNode 的话,会路由失败(如果有 defaultNode,则路由至 defaultNode)
【分片索引】5. 无论哪种模式,分片索引字段的格式化字符串 dateFormat 由用户指定
【分片索引】6. 无论哪种模式,划分不是以日历时间为准,无法对应自然月和自然年,且会受闰秒问题影响
运维注意点
【扩容】1. 带状模式中,随着 sBeginDate 之后的数据出现,分片数量的增加无需再平衡
【扩容】2. 带状模式没有自动增添分片的能力,需要运维手工提前增加分片;如果路由策略计算出的分片并不存在时,会导致失败
【扩容】3. 环状模式中,如果新旧 [sBeginDate,sEndDate] 之间有重叠,需要进行部分数据迁移;如果新旧 [sBeginDate,sEndDate] 之间没有重叠,需要数据再平衡
配置注意点
【配置项】1. 在 rule.xml 中,可配置项为 <propertyname="sBeginDate"> 、 <propertyname="sPartionDay"> 、 <propertyname="dateFormat"> 、 <propertyname="sEndDate"> 和 <propertyname="defaultNode">
【配置项】2.在 rule.xml 中配置 <propertyname="dateFormat">,符合 java.text.SimpleDateFormat 规范的字符串,用于告知 DBLE 如何解析sBeginDate和sEndDate
【配置项】3.在 rule.xml 中配置 <propertyname="sBeginDate">,必须是符合 dateFormat 的日期字符串
【配置项】4.在 rule.xml 中配置 <propertyname="sEndDate">,必须是符合 dateFormat 的日期字符串;配置了该项使用的是环状模式,若没有配置该项则使用的是带状模式
【配置项】5.在 rule.xml 中配置 <propertyname="sPartionDay">,非负整数,该分片策略以 86400000 毫秒(24 小时整)作为一份,而 sPartionDay 告诉 DBLE 把每多少份放在同一个分片
【配置项】6.在 rule.xml 中配置 <propertyname="defaultNode"> 标签,非必须配置项,不配置该项的话,用户的分片索引值没落在 mapFile 定义
H. 浏览器缓存机制简单概括和分析
对于访问的页面和请求,为了缩短网页请求资源的距离,减少延迟,并且由于缓存文件可以重复利用,还可以减少带宽,降低网络负荷,浏览器和服务器都有可能会对请求资源进行缓存,接下来的文章就简单介绍和分析浏览器的缓存机制。
深入理解浏览器的缓存机制: https://www.jianshu.com/p/54cc04190252
这篇文章已经有详细的讲解,这里就概括一下:
以首页的请求为例:
1、强制缓存策略(Expires和Cache-Control) :当浏览器发起http请求的时候,如果配置了缓存策略且缓存在有效期内,会直接使用浏览器缓存。 不使用强制缓存 ( Cache-Control=no-chache, 或者 max-age=0 )
(1)、图中请求服务器:是 max-age=0 的情况,浏览器直接请求服务器资源,而不是用本地缓存
(2)、图中磁盘缓存和内存缓存:就是浏览器使用了本地缓存而不再请求服务器资源
2、协商缓存策略(Last-Modified和If-Modified-Since, ETag和If-None-Match): 当浏览器发起http请求的时候,如果 强制缓存策略 失效,或者者禁用了强制缓存,这时候会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回304和空的响应体,直接从缓存读取,如果If-Modified-Since的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200。
不使用协商缓存 ( Cache-Control=no-store ),这个参数同时也会 禁用强制缓存。
(1)、服务器资源返回无更新,浏览器使用上次请求的资源
(2)、服务器资源有更新,返回200并返回最新的资源
3、不使用缓存策略(Cache-Control=no-store): 所有内容都不会被缓存,即不使用强制缓存,也不使用协商缓存。当response head 设置了no-store,浏览器不会对返回的资源做缓存,每次请求都是直接请求服务器。这可以保证浏览器每次都能拿最新的资源,即使资源对比上次请求没有任何更新,但同时也降低了页面的响应速度,和增加了网络的IO与服务器的压力。
可以明显的看到请求时间,请求服务器资源时间 >> 请求磁盘缓存 > 请求内存缓存,所以合适的缓存策略,可以在不影响业务的情况下,极大地提升客户体验和后台服务器压力。