spring 缓存 详细说明

spring  缓存 详细说明
spring  缓存 详细说明

Spring使用Cache

从3.1开始,Spring引入了对Cache的支持。其使用方法和原理都类

似于Spring对事务管理的支持。Spring Cache是作用在方法上的,其核心思想是这样的:当我们在调用一个缓存方法时会把该方法参数和返回结果作为一个键值对存放在缓存中,等到下次利用同样的参数来调用该方法时将不再执行该方法,而是直接从缓存中获取结果进行返回。所以在使用Spring Cache的时候我们要保证我们缓存的方法对于相同的方法参数要有相同的返回结果。

使用Spring Cache需要我们做两方面的事:

?声明某些方法使用缓存

?配置Spring对Cache的支持

和Spring对事务管理的支持一样,Spring对Cache的支持也有基于注

解和基于XML配置两种方式。下面我们先来看看基于注解的方式。

1基于注解的支持

Spring为我们提供了几个注解来支持Spring Cache。其核心主要是

@Cacheable和@CacheEvict。使用@Cacheable标记的方法在执行后Spring Cache 将缓存其返回结果,而使用@CacheEvict标记的方法会在方法执行前或者执行后移除Spring Cache中的某些元素。下面我们将来详细介绍一下Spring基于注解对Cache的支持所提供的几个注解。

1.1 @Cacheable

@Cacheable可以标记在一个方法上,也可以标记在一个类上。当标记在一个方法上时表示该方法是支持缓存的,当标记在一个类上时则表示该类所有的方法都是支持缓存的。对于一个支持缓存的方法,Spring会在其被调用后将其

返回值缓存起来,以保证下次利用同样的参数来执行该方法时可以直接从缓存中获取结果,而不需要再次执行该方法。Spring在缓存方法的返回值时是以键值

对进行缓存的,值就是方法的返回结果,至于键的话,Spring又支持两种策略,默认策略和自定义策略,这个稍后会进行说明。需要注意的是当一个支持缓存的方法在对象内部被调用时是不会触发缓存功能的。@Cacheable可以指定三个属性,value、key和condition。

1.1.1value属性指定Cache名称

value属性是必须指定的,其表示当前方法的返回值是会被缓存在哪个Cache上的,对应Cache的名称。其可以是一个Cache也可以是多个Cache,当需要指定多个Cache时其是一个数组。

@Cacheable("cache1")//Cache是发生在cache1上的

public User find(Integer id) {

returnnull;

}

@Cacheable({"cache1", "cache2"})//Cache是发生在cache1和cache2上的

public User find(Integer id) {

returnnull;

}

1.1.2使用key属性自定义key

key属性是用来指定Spring缓存方法的返回结果时对应的key的。该属性支持SpringEL表达式。当我们没有指定该属性时,Spring将使用默认策略生成key。我们这里先来看看自定义策略,至于默认策略会在后文单独介绍。

自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。下面是几个使用参数作为key 的示例。

@Cacheable(value="users", key="#id")

public User find(Integer id) {

returnnull;

}

@Cacheable(value="users", key="#p0")

public User find(Integer id) {

returnnull;

}

@Cacheable(value="users", key="#user.id")

public User find(User user) {

returnnull;

}

@Cacheable(value="users", key="#p0.id")

public User find(User user) {

returnnull;

}

除了上述使用方法参数作为key之外,Spring还为我们提供了一个root 对象可以用来生成key。通过该root对象我们可以获取到以下信息。

当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。如:

@Cacheable(value={"users", "xxx"}, key="caches[1].name")

public User find(User user) {

returnnull;

}

1.1.3condition属性指定发生的条件

有的时候我们可能并不希望缓存一个方法所有的返回结果。通过condition属性可以实现这一功能。condition属性默认为空,表示将缓存所有的调用情形。其值是通过SpringEL表达式来指定的,当为true时表示进行缓存处理;当为false时表示不进行缓存处理,即每次调用该方法时该方法都会执行一次。如下示例表示只有当user的id为偶数时才会进行缓存。

@Cacheable(value={"users"}, key="#user.id",

condition="#user.id%2==0")

public User find(User user) {

System.out.println("find user by user " + user);

return user;

}

1.2@CachePut

在支持Spring Cache的环境下,对于使用@Cacheable标注的方法,Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素,如果存在就不再执行该方法,而是直接从缓存中获取结果进行返回,否则才会执行并将返回结果存入指定的缓存中。@CachePut也可以声明一个方法支持缓存功能。与@Cacheable不同的是使用@CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果,而是每次都会执行该方法,并将执行结果以键值对的形式存入指定的缓存中。

@CachePut也可以标注在类上和方法上。使用@CachePut时我们可以指定的属性跟@Cacheable是一样的。

@CachePut("users")//每次都会执行方法,并将结果存入指定的缓存中public User find(Integer id) {

returnnull;

}

1.3@CacheEvict

@CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。

@CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与@Cacheable对应的属性类似。即value表示清除操作是发生在哪些Cache上的(对应Cache的名称);key表示需要清除的是哪个key,如未指定则会使用默认策略生成的key;condition表示清除操作发生的条件。下面我们来介绍一下新出现的两个属性allEntries和beforeInvocation。

1.3.1allEntries属性

allEntries是boolean类型,表示是否需要清除缓存中的所有元素。默认为false,表示不需要。当指定了allEntries为true时,Spring Cache将忽略指定的key。有的时候我们需要Cache一下清除所有的元素,这比一个一个清除元素更有效率。

@CacheEvict(value="users", allEntries=true)

public void delete(Integer id) {

System.out.println("delete user by id: " + id);

}

1.3.2beforeInvocation属性

清除操作默认是在对应方法成功执行之后触发的,即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变

触发清除操作的时间,当我们指定该属性值为true时,Spring会在调用该方法之前清除缓存中的指定元素。

@CacheEvict(value="users", beforeInvocation=true)

public void delete(Integer id) {

System.out.println("delete user by id: " + id);

}

其实除了使用@CacheEvict清除缓存元素外,当我们使用Ehcache作为实现时,我们也可以配置Ehcache自身的驱除策略,其是通过Ehcache的配置文件来指定的。由于Ehcache不是本文描述的重点,这里就不多赘述了,想了解更多关于Ehcache的信息,请查看我关于Ehcache的专栏。

1.4@Caching

@Caching注解可以让我们在一个方法或者类上同时指定多个Spring Cache相关的注解。其拥有三个属性:cacheable、put和evict,分别用于指定@Cacheable、@CachePut和@CacheEvict。

@Caching(cacheable = @Cacheable("users"), evict =

{ @CacheEvict("cache2"),

@CacheEvict(value = "cache3", allEntries = true) }) public User find(Integer id) {

returnnull;

}

1.5使用自定义注解

Spring允许我们在配置可缓存的方法时使用自定义的注解,前提是自定义的注解上必须使用对应的注解进行标注。如我们有如下这么一个使用

@Cacheable进行标注的自定义注解。

@Target({ElementType.TYPE, ElementType.METHOD})

@Retention(RetentionPolicy.RUNTIME)

@Cacheable(value="users")

public @interface MyCacheable {

}

那么在我们需要缓存的方法上使用@MyCacheable进行标注也可以达到同样的效果。

@MyCacheable

public User findById(Integer id) {

System.out.println("find user by id: " + id);

User user = new User();

user.setId(id);

user.setName("Name" + id);

return user;

}

2配置Spring对Cache的支持

2.1声明对Cache的支持

2.1.1基于注解

配置Spring对基于注解的Cache的支持,首先我们需要在Spring的配置文件中引入cache命名空间,其次通过就可以启用Spring对基于注解的Cache的支持。

xmlns:xsi="https://www.360docs.net/doc/9715829748.html,/2001/XMLSchema-instance"

xmlns:cache="https://www.360docs.net/doc/9715829748.html,/schema/cache"

xsi:schemaLocation="https://www.360docs.net/doc/9715829748.html,/schema/be ans

https://www.360docs.net/doc/9715829748.html,/schema/beans/spring-beans-3 .0.xsd

https://www.360docs.net/doc/9715829748.html,/schema/cache

https://www.360docs.net/doc/9715829748.html,/schema/cache/spring-cache.x sd">

有一个cache-manager属性用来指定当前所使用的CacheManager对应的bean的名称,默认是cacheManager,所以当我们的CacheManager的id为cacheManager时我们可以不指定该参数,否则就需要我们指定了。

还可以指定一个mode属性,可选值有proxy和aspectj。默认是使用proxy。当mode为proxy时,只有缓存方法在外部被调用的时候Spring Cache才会发生作用,这也就意味着如果一个缓存方法在其声明对象内部被调用时Spring Cache是不会发生作用的。而mode为aspectj 时就不会有这种问题。另外使用proxy时,只有public方法上的@Cacheable等标注才会起作用,如果需要非public方法上的方法也可以使用Spring Cache 时把mode设置为aspectj。

此外,还可以指定一个

proxy-target-class属性,表示是否要代理class,默认为false。我们前面提到的@Cacheable、@cacheEvict等也可以标注在接口上,这对于基于接口的代理来说是没有什么问题的,但是需要注意的是当我们设置proxy-target-class为

true或者mode为aspectj时,是直接基于class进行操作的,定义在接口上的@Cacheable等Cache注解不会被识别到,那对应的Spring Cache也不会起作用了。

需要注意的是只会去寻找定义在同一个ApplicationContext下的@Cacheable等缓存注解。

2.1.2基于XML配置

除了使用注解来声明对Cache的支持外,Spring还支持使用XML来声明对Cache的支持。这主要是通过类似于aop:advice的cache:advice来进行的。在cache命名空间下定义了一个cache:advice元素用来定义一个对于Cache的advice。其需要指定一个cache-manager属性,默认为cacheManager。cache:advice下面可以指定多个cache:caching元素,其有点类似于使用注解时的@Caching注解。cache:caching元素下又可以指定cache:cacheable、cache:cache-put和cache:cache-evict元素,它们类似于使用注解时的

@Cacheable、@CachePut和@CacheEvict。下面来看一个示例:

all-entries="true"/>

上面配置定义了一个名为cacheAdvice的cache:advice,其中指定了将缓存findById方法和find方法到名为users的缓存中。这里的方法还可以使用通配符“*”,比如“find*”表示任何以“find”开始的方法。

有了cache:advice之后,我们还需要引入aop命名空间,然后通过aop:config指定定义好的cacheAdvice要应用在哪些pointcut上。如:

pointcut="execution(* https://www.360docs.net/doc/9715829748.html,erService.*(..))"/>

上面的配置表示在调用https://www.360docs.net/doc/9715829748.html,erService中任意公共方法时将使用cacheAdvice对应的cache:advice来进行Spring Cache处理。更多关于Spring Aop的内容不在本文讨论范畴内。

2.2配置CacheManager

CacheManager是Spring定义的一个用来管理Cache的接口。Spring自身已经为我们提供了两种CacheManager的实现,一种是基于Java API的ConcurrentMap,另一种是基于第三方Cache实现——Ehcache,如果我们需要使用其它类型的缓存时,我们可以自己来实现Spring的CacheManager接口或AbstractCacheManager抽象类。下面分别来看看Spring已经为我们实现好了的两种CacheManager的配置示例。

2.2.1基于ConcurrentMap的配置

class="org.springframework.cache.support.SimpleCacheManager">

class="org.springframework.cache.concurrent.ConcurrentMapCache FactoryBean" p:name="xxx"/>

上面的配置使用的是一个SimpleCacheManager,其中包含一个名为“xxx”的ConcurrentMapCache。

2.2.2基于Ehcache的配置

class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cache-manager-ref="ehcacheManager"/>

class="org.springframework.cache.ehcache.EhCacheManagerFactory Bean" p:config-location="ehcache-spring.xml"/>

上面的配置使用了一个Spring提供的EhCacheCacheManager来生成一个Spring的CacheManager,其接收一个Ehcache的CacheManager,因为真正用来存入缓存数据的还是Ehcache。Ehcache的CacheManager是通过Spring提供的EhCacheManagerFactoryBean来生成的,其可以通过指定ehcache的配置文件位置来生成一个Ehcache的CacheManager。若未指定则将按照Ehcache的默认规则取classpath根路径下的ehcache.xml文件,若该文件也不存在,则获取Ehcache对应jar包中的ehcache-failsafe.xml文件作为配置文件。更多关于Ehcache的内容这里就不多说了,它不属于本文讨论的内容,欲了解更多关于Ehcache的内容可以参考我之前发布的Ehcache系列文章,也可以参考官方文档等。

3键的生成策略

键的生成策略有两种,一种是默认策略,一种是自定义策略。

3.1默认策略

默认的key生成策略是通过KeyGenerator生成的,其默认策略如下:?如果方法没有参数,则使用0作为key。

?如果只有一个参数的话则使用该参数作为key。

?如果参数多余一个的话则使用所有参数的hashCode作为key。

如果我们需要指定自己的默认策略的话,那么我们可以实现自己的KeyGenerator,然后指定我们的Spring Cache使用的KeyGenerator为我们自己定义的KeyGenerator。

使用基于注解的配置时是通过cache:annotation-driven指定的.

class="https://www.360docs.net/doc/9715829748.html,erKeyGenerator"/>

而使用基于XML配置时是通过cache:advice来指定的。

需要注意的是此时我们所有的Cache使用的Key的默认生成策略都是同一个KeyGenerator。

3.2自定义策略

自定义策略是指我们可以通过Spring的EL表达式来指定我们的key。这里的EL表达式可以使用方法参数及它们对应的属性。使用方法参数时我们可以直接使用“#参数名”或者“#p参数index”。下面是几个使用参数作为key 的示例。

@Cacheable(value="users", key="#id")

public User find(Integer id) {

returnnull;

}

@Cacheable(value="users", key="#p0")

returnnull;

}

@Cacheable(value="users", key="#user.id")

public User find(User user) {

returnnull;

}

@Cacheable(value="users", key="#p0.id")

public User find(User user) {

returnnull;

}

除了上述使用方法参数作为key之外,Spring还为我们提供了一个root 对象可以用来生成key。通过该root对象我们可以获取到以下信息。

当我们要使用root对象的属性作为key时我们也可以将“#root”省略,因为Spring默认使用的就是root对象的属性。如:

@Cacheable(value={"users", "xxx"}, key="caches[1].name")

returnnull;

}

4Spring单独使用Ehcache

前面介绍的内容是Spring内置的对Cache的支持,其实我们也可以通过Spring自己单独的使用Ehcache的CacheManager或Ehcache对象。通过在Application Context中配置EhCacheManagerFactoryBean和EhCacheFactoryBean,我们就可以把对应的EhCache的CacheManager和Ehcache 对象注入到其它的Spring bean对象中进行使用。

4.1EhCacheManagerFactoryBean

EhCacheManagerFactoryBean是Spring内置的一个可以产生Ehcache的CacheManager对象的FactoryBean。其可以通过属性configLocation指定用于创建CacheManager的Ehcache配置文件的路径,通常是ehcache.xml文件的路径。如果没有指定configLocation,则将使用默认位置的配置文件创建CacheManager,这是属于Ehcache自身的逻辑,即如果在classpath根路径下存在ehcache.xml文件,则直接使用该文件作为Ehcache的配置文件,否则将使用ehcache-xxx.jar中的ehcache-failsafe.xml文件作为配置文件来创建Ehcache 的CacheManager。此外,如果不希望创建的CacheManager使用默认的名称(在ehcache.xml文件中定义的,或者是由CacheManager内部定义的),则可以通过cacheManagerName属性进行指定。下面是一个配置EhCacheManagerFactoryBean的示例。

class="org.springframework.cache.ehcache.EhCacheManagerFactory Bean">

value="/WEB-INF/config/ehcache.xml"/>

value="cacheManagerName"/>

4.2EhCacheFactoryBean

EhCacheFactoryBean是用来产生Ehcache的Ehcache对象的FactoryBean。定义EhcacheFactoryBean时有两个很重要的属性我们可以来指定。一个是cacheManager属性,其可以指定将用来获取或创建Ehcache的CacheManager对象,若未指定则将通过CacheManager.create()获取或创建默认的CacheManage r。另一个重要属性是cacheName,其表示当前EhCacheFactoryBean对应的是CacheManager中的哪一个Ehcache对象,若未指定默认使用beanName作为cacheName。若CacheManager中不存在对应cacheName 的Ehcache对象,则将使用CacheManager创建一个名为cacheName的Cache对象。此外我们还可以通过EhCacheFactoryBean的timeToIdle、timeToLive等属性指定要创建的Cache的对应属性,注意这些属性只对CacheManager中不存在对应Cache时新建的Cache才起作用,对已经存在的Cache将不起作用,更多属性设置请参考Spring的API文档。此外还有几个属性是对不管是已经存在还是新创建的Cache都起作用的属性:statisticsEnabled、sampledStatisticsEnabled、disabled、blocking和cacheEventListeners,其中前四个默认都是false,最后一个表示为当前Cache指定CacheEventListener。下面是一个定义EhCacheFactoryBean的示例。

class="org.springframework.cache.ehcache.EhCacheManagerFactory Bean">

value="/WEB-INF/config/ehcache.xml"/>

value="cacheManagerName"/>

class="org.springframework.cache.ehcache.EhCacheFactoryBean">

Redis面试专题及答案

redis和memcached什么区别?为什么高并发下有时单线程的redis比多线程的memcached效率要高? 区别: 1.mc可缓存图片和视频。rd支持除k/v更多的数据结构; 2.rd可以使用虚拟内存,rd可持久化和aof灾难恢复,rd通过主从支持数据备份; 3.rd可以做消息队列。 原因:mc多线程模型引入了缓存一致性和锁,加锁带来了性能损耗。 redis主从复制如何实现的?redis的集群模式如何实现?redis的key是如何寻址的? 主从复制实现:主节点将自己内存中的数据做一份快照,将快照发给从节点,从节点将数据恢复到内存中。之后再每次增加新数据的时候,主节点以类似于mysql的二进制日志方式将语句发送给从节点,从节点拿到主节点发送过来的语句进行重放。 分片方式: -客户端分片 -基于代理的分片 ●Twemproxy ●codis -路由查询分片 ●Redis-cluster(本身提供了自动将数据分散到Redis Cluster不同节点的能力,整个数据集合的某个数据子集存储在哪个节点对于用户来说是透明的) redis-cluster分片原理:Cluster中有一个16384长度的槽(虚拟槽),编号分别为0-16383。每个Master节点都会负责一部分的槽,当有某个key被映射到某个Master负责的槽,那么这个Master负责为这个key提供服务,至于哪个Master节点负责哪个槽,可以由用户指定,也可以在初始化的时候自动生成,只有Master才拥有槽的所有权。Master节点维护着一个16384/8字节的位序列,Master节点用bit来标识对于某个槽自己是否拥有。比如对于编号为1的槽,Master只要判断序列的第二位(索引从0开始)是不是为1即可。这种结构很容易添加或者删除节点。比如如果我想新添加个节点D, 我需要从节点A、B、C中得部分槽到D上。 使用redis如何设计分布式锁?说一下实现思路?使用zk可以吗?如何实现?这两种有什么区别? redis: 1.线程A setnx(上锁的对象,超时时的时间戳t1),如果返回true,获得锁。 2.线程B 用get获取t1,与当前时间戳比较,判断是是否超时,没超时false,若超时执行第3步; 3.计算新的超时时间t2,使用getset命令返回t3(该值可能其他线程已经修改过),如果 t1==t3,获得锁,如果t1!=t3说明锁被其他线程获取了。 4.获取锁后,处理完业务逻辑,再去判断锁是否超时,如果没超时删除锁,如果已超时,不用处理(防止删除其他线程的锁)。 zk: 1.客户端对某个方法加锁时,在zk上的与该方法对应的指定节点的目录下,生成一个唯一的瞬时有序节点node1; 2.客户端获取该路径下所有已经创建的子节点,如果发现自己创建的node1的序号是最小的,就认为这个客户端获得了锁。 3.如果发现node1不是最小的,则监听比自己创建节点序号小的最大的节点,进入等待。

Android客户端缓存方案

概述: 客户端缓存机制是android应用开发中非常重要的一项工作,使用缓存机制不仅仅可以为用户节省3G流量,同时在用户体验方面也是非常好的选择. 缓存机制分为两部分,一部分是文字缓存,另一部分是多媒体文件缓存. 缓存文件保存策略: 1.文字缓存: 文字缓存应该分为两种,一种是更新比较频繁的区域,一种是更新不频繁的区域. 根据两者的更新频率区分它们的过期时间. 更新比较频繁的区域,它的缓存过期时间应该为应用程序内(即应用程序从打开到关闭的这段时间).这种情况会有专门的缓存文件夹存放该类缓存文件,以及专门的缓存数据库表存放信息.每次应用程序启动的时候都会先将该类数据清空. 另一种很少更新的区域,它的缓存不设置过期时间,而是提供一个按钮或者Menu可以让用户选择手动更新(如我的好友列表,我的订阅,我的分享.等等….) 具体的文字缓存划分,详见附录1. (1)通常情况下,我们与服务器交互都是采用JSON格式获取数据的,获取的JSON数 据仅仅是一段字符串,我们可以考虑将这些字符串使用文件流写入一个TXT,保存到 SD卡中,在数据库添加该数据的记录.添加数据库记录时,提供两个关键字段,一个是 请求的URL,另一个则是本地保存后的文件地址.日后每次向服务器发起请求之前都会根据URL在数据库中检索. 该方法好处:降低系统数据库数据量,不会出现数据库满了的现象. 缺点:IO操作频繁,有时代码书写有误会造成内存泄露等状况. (2)将JSON数据解析后装入List对象中,然后遍历List,将数据统统写入相应的 数据库表结构中,以后每次向服务器发起请求之前可以先在数据库中检索,如果有直接返回. 该方法好处:如果本地存在文字缓存,那么读取缓存速度快. 缺点:增加数据库数据量. 2.多媒体文件缓存 (1)图片缓存 图片的缓存可以根据当前日期,时间为名字缓存到SD卡中的指定图片缓存目录, 同时数据库中做相应记录,记录办法可以采用两个关键字段控制,一个字段是该图片 的URL地址,另一个字段是该图片的本机地址.取图片时根据URL在数据中检索, 如果没有则连接服务器下载,下载之后再服务器中作出相应记录. (2)视频文件缓存 考虑到视频文件就是动画片,每一集的大小应该超过20MB,如果边播放边下载的话 用户的3G流量负担是很大的,而且用户看完一集动画片,基本上不会再去看第二遍. 从这个状况来看,建议不要对视频文件进行下载缓存.另外也能降低程序员的编码负 担.

FTP文件下载不能及时更新

FTP文件下载“不能及时更新”都是IE缓存的错 事件回放:学期末,信息技术课学生正在微机室进行在线考试。”上面有答案,”下面有同学小声议论经,我看了一下,原来我在制作试卷时将答案与试题做成了一个文档,学生在下载试卷的同时,答案也就下载了。我赶紧嘱咐学生自觉考试,同时将答案自觉删除。幸好是第一个班,我赶紧登陆到学校FTP服务器上,将考试文档中答案删除。每想到第二个班考试时,下载的考试文档还有答案。我直接到FTP服务器上操作,发现确实已经删除了。怎么加事?经过一番分析,原来都是IE缓存引起的。 关于IE缓存 为了提高访问网页的速度,Internet Explorer浏览器会采用累积式加速的方法,将你曾经访问的网页内容(包括图片以及cookie文件等)存放在电脑里。这个存放空间,我们就称它为IE缓存。以后我们每次访问网站时,IE会首先搜索这个目录,如果其中已经有访问过的内容,那IE就不必从网上下载,而直接从缓存中调出来,从而提高了访问网站的速度。 FTP默认工作方式也是通过IE打开,我们不难分析产生这种现象的原因: 从FTP服务器下载文档到本地或是直接打开文档,首先到IE缓存检查有没有同名的文件存在,如果有,就直接从IE缓存打开或下载。如果没有,先下载到IE缓存,然后再从IE缓存下载到本地,当在FTP服务器上对文件内容修改时,只要文件名没改变时,即使内容变了或者文件大小变了,客户端先检查本地IE缓存,如果存在同名(不管大小或文件最后修改时间),就直接从本地IE缓存下载,当然还是原来那个文件了。 小秘密:关于文件在缓存中的位置。在IE的“工具”菜单下选择“Internet选项”,然后在“常规”选项卡中你会看到有“Internet临时文件”这一项,单击“设置”按钮,然后在弹出的“设置”对话框中就可以看到IE缓存的位置,winxp与win7略有不同了。这里有一个不能不说的秘密了。我开始在实验中,在该缓存目录下没有发现任何我要下载的文档,通过WINDOWS的文件查找功能在该目录下也没有找到任何文档了,其实下载的文档应该还是从缓存COPY过来的,因为在FTP服务端已经更改了内容了。后来查阅了相关资料才知道在系统提示的IE缓存目录下还有一个文件夹“\Content.IE5”,它即不是隐藏的也不是系统的,所以不通过手工输入,是无法进入的。当进入到该目录下,你看到那些在"content.ie5"目录下以数字和字母命名的文件夹了么?这是微软试图通过使用复杂的文件名来使他的计划越发难以理解,这些数字和字母命名的文件夹就是微软生成的用来保存你的cookies和缓存的文件夹,如下图所示。

java开发工程师简历

求职意向:java软件工程师 工作经验:2年 到岗时间:一周之内 期望薪资:面议 个人信息 年龄:25岁邮箱: 手机: 现居地:北京通州 专业技能 ?熟悉掌握JavaScript,Ajax,jQuery,JSON等前台技术并能够熟练使用EasyUI,zTree,ECharts等插件 ?熟悉掌握Servlet,Cookie,Session,JDBC,JavaBean,EL表达式,JSTL 等技术,深入了解MVC开发模式 ?熟悉使用Struts2框架,包括拦截器,OGNL表达式,Ajax并熟悉Struts2的工作流程 ?熟悉使用Spring框架,包括IOC和DI,AOP编程,声明式事务处理以及代理模式 ?熟悉使用Hibernate框架,包括一对多,多对多的对象关系映射,HQL,对象状态转换,数据缓存等 ?熟练运用SpringMVC,Mybatis 进行项目开发,掌握shiro 安全框架 ?熟悉使用MySQL和oracle数据库,使用其编写复杂的SQL语句,具有Mysql数据库的优化经验;掌握redis数据缓存技术 ?熟悉使用MyEclipse、HBilder,PLSQLDevelopment等开发工具,熟悉使用maven 项目管理工具,以及SVN 服务器的使用 ?熟悉Tomcat服务器的应用部署和集群配置

工作经历 毗邻智慧软件开发科技有限公司 担任职位:java软件开发师 ●初期主要实现项目的维护和个性化需求的搜集整理 ●完成项目模块的编码和测试工作 项目经验 项目名称:泉翼达商城 框架构建:Spring + SpringMVC + Mybatis + Mysql + zTree +PageHelper+ + EasyUI +CKeditor+Nginx+Redis 项目描述:此系统主要实现的功能是用户网上预订果蔬功能,包括交易系统和后台管理系统、会员系统、积分系统、支付系统、物流系统、单点登录系统 功能模块:商品信息展示、购物车管理、订单管理、用户管理、商品管理、积分管理、支付管理等功能模块 项目职责: ?负责了此系统的商品信息模块和商品管理模块的用户需求分析,完成了文档的设计与编写 ?前台交易系统负责了商品信息模块和购物车管理模块的代码编写,实现了商品基本信息(如商品预览、商品明细、分类检索)的功能,以及购物车管理模块(实现添 加商品、删除列表、数量修改、清空购物车、结算功能) ?后台管理系统负责商品管理(实现商品列表、商品发布、商品删除、商品修改功能)和用户管理模块(实现登入/登出、用户注册、信息修改功能)

memcached&redis性能测试

一、Memcached 1.1、memcached简介 Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web 应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提供动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。但是它并不提供冗余(例如,复制其hashmap条目);当某个服务器S停止运行或崩溃了,所有存放在S上的键/值对都将丢失。 Memcached由Danga Interactive开发,其最新版本发布于2010年,作者为Anatoly Vorobey和Brad Fitzpatrick。用于提升LiveJournal . com访问速度的。LJ每秒动态页面访问量几千次,用户700万。Memcached将数据库负载大幅度降低,更好的分配资源,更快速访问。 1.2、Memcached是如何工作的 Memcached的神奇来自两阶段哈希(two-stage hash)。Memcached就像一个巨大的、存储了很多对的哈希表。通过key,可以存储或查询任意的数据。客户端可以把数据存储在多台memcached上。当查询数据时,客户端首先参考节点列表计算出key的哈希值(阶段一哈希),进而选中一个节点;客户端将请求发送给选中的节点,然后memcached节点通过一个内部的哈希算法(阶段二哈希),查找真正的数据(item)。举个列子,假设有3个客户端1, 2, 3,3台memcached A, B, C:Client 1想把数 据”tuletech”以key “foo”存储。Client 1首先参考节点列表(A, B, C),计算key “foo”的哈希值,假设memcached B被选中。接着,Client 1直接connect 到memcached B,通过key “foo”把数据”tuletech”存储进去。Client 2使用与Client 1相同的客户端库(意味着阶段一的哈希算法相同),也拥有同样的

缓存机制

3.1、缓存策略 3.1.1、一级缓存 之前每一个数据库操作都是一个Session,那么对于Session来说本身是存在着缓存,可以保留之前的查询结果。 但是对于Session的缓存只针对于一个Session有效,那么如果现在想针对于多个Session 有作用,则必须在SessionFactory上配置缓存,那么这样的缓存称为二级缓存。 在Hiernate按ID查询有两个方法:load、get 那么下面使用以上的查询方法,查询两次 程序虽然调用了两次load方法,但是只发出了一条的查询命令,证明,第一次的查询结果被保存下来了,那么这就是一级缓存。

与之前的相比,查询了两次操作,所以此时,证明一级缓存只是针对于一个Session起作用的。但是一级缓存是无法关闭的,始终会存在。

从运行结果可以发现,如果之前先进行了保存操作,那么之后再查询的话也不会重新发出查询语句。证明实体被缓存下来。 问题: 如果现在要求使用程序插入100000万条记录?该怎么办? 如果使用Hibernate处理的话,则可能会出现内存的溢出,所以在这种情况下首先是绝对不建议使用Hibernate完成的,就使用最基本的JDBC操作完成即可。 如果非要使用Hibernate做,则必须使用到Session中关于缓存的一些操作方法:·清空Session中的所有缓存:clear() ·清空Session中一个指定的实体:evict(Object obj) 例如:下面验证clear()方法 因为程序中,将所有的缓存清空了,所以之后再查询相同实体的时候,在Session中已

以上因为只清空了一个实体,所以只发出了三个查询语句。 那么就可以通过以上的方式完成100W条记录的插入 思路:按照每十条清空缓存的操作,并将缓存中的内容强制性的写到数据库之中 3.1.2、二级缓存(重点) 在Hibernate本身中支持了多种的二级缓存组件。本次使用EHcache。如果要想使用ehcache话,则首先必须进行配置,配置ehcache的缓存文件。 ehcache.xml:

Redis的5个常见使用场景

Redis的5个常见使用场景概括 大家平时在使用Redis的时候有没有总结过Redis常用于哪些场景呢。下面科多老师带着大家一起来总结一下,希望能够帮助到各位同学。 1、会话缓存(Session Cache) 最常用的一种使用Redis的情景是会话缓存(session cache)。用Redis 缓存会话比其他存储(如Memcached)的优势在于:Redis提供持久化。当维护一个不是严格要求一致性的缓存时,如果用户的购物车信息全部丢失,大部分人都会不高兴的,现在,他们还会这样吗? 幸运的是,随着 Redis 这些年的改进,很容易找到怎么恰当的使用Redis 来缓存会话的文档。甚至广为人知的商业平台Magento也提供Redis的插件。 2、全页缓存(FPC) 除基本的会话token之外,Redis还提供很简便的FPC平台。回到一致性 问题,即使重启了Redis实例,因为有磁盘的持久化,用户也不会看到页面加载速度的下降,这是一个极大改进,类似PHP本地FPC。 再次以Magento为例,Magento提供一个插件来使用Redis作为全页缓存后端。 此外,对WordPress的用户来说,Pantheon有一个非常好的插件wp-redis,这个插件能帮助你以最快速度加载你曾浏览过的页面。 3、队列 Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis 能作为一个很好的消息队列平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操作。 如果你快速的在Google中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为broker,你可以从这 里去查看。 4、排行榜/计数器 Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set) 和有序集合(Sorted Set)也使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。所以,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”,我们只需要像下面一样执行即可: 当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执行: ZRANGE user_scores 0 10 WITHSCORES

多层技术架构JAVA

多层技术架构 本系统构建于J2EE平台,采用分层提供服务支持的设计思想,将系统划分为数据库层、中间件层、EMALL基础服务层、业务表现层和系统接口层。系统对每一层定义明确的功能接口,同时在层次内实现组件化的接口实现。层次化、模块组件化的实现,使系统具备了最大程度的灵活度,从而能对业务需求的变化作出快速的反应,使系统具有很好的扩展性。 首先我们来看一个系统技术架构图: 上图可以清晰的了解到整个系统的层次划分,系统从最底部的数据库层开始,一层一层的向上提供接口服务,最终实现用户按业务要求的可见操作界面和其他系统接口。各层次专著于自身功能的接口实现,整个层次保持相对的稳定。系统通过不改变接口,各个层次、各个组件进行优化的策略,能在不影响整个业务的前提下,不断的完善和改进。 一、数据库层 对于平台中的所有应用,都存在着各种各样的配置信息、业务数据、系统运行状态等信息。数据库层对这些数据信息本身进行归档,提供快速查询的底层接口,并保证数据的完整性、可靠性。 在数据库方面,我们采用Oracle或者是MySQL。这两种数据库分别有不同的适用环境。 1、Oracle ◆适合大型的电子商务应用。 ◆能使用所有的网客通平台功能。如访问量排行榜、降价排行榜、销售排行榜、访问量统计等等,就以往的经验来看,这些功能每天要处理的数据都会超过一千万。这种数据量如果使用传统的统计方法,统计一次的时间就可能会以天来计算了。如果使用Oracle,再配合我们专门对Oracle进行优化的高效率的统计程序,那么只需十数秒便可完成。 ◆此外,如果只用一台数据库无法应付日益增长的服务器访问量,可以使用Oracle RAC(真正应用集群),通过增加数据库服务器进行集群。 2、MySQL ◆适合中小型的电子商务应用。 ◆无法使用网客通平台一些高级应用,如排行榜、统计分析、MIS系统对接等。这是由于MySQL设计上强调访问速度,牺牲了一些数据库的高级功能,虽然用程序也可以实现这些功能,但是在性能上无法满足需求。 ◆不支持数据库集群。

memcache、redis、tair性能对比测试报告材料

memcache、redis、tair性能对比测试报告 第1章限制条件 前一周所做的分布缓存技术预言中有包括ehcache、memcache、redis、tair,还包括了基于MongoDB的分布式技术。测试中,考虑到各自功能的差异化特点,其中选择了memcache、redis、tair功能特性相近的缓存服务器进行性能对比,所以ehcache、MongoDB将不做为本次测试的规范,其原因如下: 1)Ehcache是组件级别的缓存,要搭建一个独立的缓存服务器,需要用到ehcache server 模块,这是个war包,能运行在web 容器中,决定整个缓存服务器性能的好坏因素太多,比如web服务器,集群方式等。跟memcache、redis、tair没有对比性。 2)MongoDB是面向文档的数据库,跟缓存没有可比性。 第2章测试场景概述 性能测试包括单机环境和分布式环境,主要针对memcache、redis、tair各缓存服务器在缓存了不同级别的数据下,多个线程并发操作向缓存set/get缓存数据,考虑到网络方面的负载,又将每次set/get操作的缓存数据的大小分为三个不同的级别:1KB,10KB,100KB,通过对上述的条件进行排列,取得以下的测试场景。 第3章单机环境测试 3.1.测试场景: 1.当各缓存的数据库空时,以单线程通过各缓存客户端set调用向服务端推送数据,比较 10000操作所消耗的时间,以上动作通过使用不同大小的单个缓存对象重复三次。2.在场景一完成的情况下,以单线程通过各缓存客户端get调用向服务端获取数据,比较 10000操作所消耗的时间,以上动作通过使用不同大小的单个缓存对象重复三次。3.并发200个线程通过缓存软件的客户set调用向服务端推送数据,每个线程完成10000 次的操作,比较服务器的tps大小,以上动作通过使用不同大小的单个缓存对象重复三

缓存管理需求说明

缓存管理功能需求说明 缓存管理开发背景 缓存管理功能的开发,意在减少系统对数据库的过多访问,通过减少对数据库的访问次数,改用访问内存的方式,提升系统的性能。直接从内存获取数据,较之从数据库获取数据,效率可以得到显著的提升。 系统由于多次查询数据库,消耗大量系统资源,且查询效率可能因为开发者的个人能力导致查询效率不高,或占用过多资源影响系统性能。使用缓存管理,系统只有第一次查询访问数据库,而后皆通过访问内存取得数据,不需要在计较这次查询的SQL是否过于复杂,是否效率低下,直接取得数据返回即可。 第一部分、缓存管理 缓存管理提供了缓存工具类CacheUtils以供开发者对缓存进行自定义开发。如果开发者需要自己开发某功能需要涉及缓存管理则可以借助使用CacheUtils工具类来完成。本地缓存管理和redis 缓存管理的区分在于redis是否正确连接且启动。注意,是正确连接并且启动redis服务器。 关于开发者需要自行开发某功能的缓存管理需要了解CacheUtils怎么使用可以查看《缓存管理开发说明》 本地缓存管理 本地缓存管理是在redis没有正常启动运行的时候系统提供的缓存管理方式。本地缓存管理暂无任何持久化操作。对于缓存中的所有数据,在应用重启后一律清空,需要重新载入缓存。本地缓存

管理采用的是标准的key-value形式保存,于Java中采用的结构形式为HashMap结构,HashMap 有利于快速的存取,因而采用该结构保存本地缓存。其中key的类型为string,value的类型为object。本地缓存管理对于类型的限制基本没有。Value可以置入任何Java支持的对象。 本地缓存管理中,保存进入缓存只需要使用CacheUtils中的save方法进行保存即可,保存的数据在本地缓存中不做多余的处理,直接置入缓存中。由于采用的是以Object类型的形式保存,并不会对保存的数据进行转换,获取保存的缓存数据时直接使用CacheUtils中的get方法即可取得保存的数据,达到怎么存就怎么取,存什么取什么。无需更多的变换数据结构,更不会导致因为存储导致类型的变换或者数据的丢失。 由于存什么取得的就是什么,因而直接修改取得的数据对象有可能导致缓存数据也被修改。Redis缓存管理 Redis缓存管理需要开启redis服务器并正确配置连接信息,系统会在启动的时候检测redis是否可以正常连接启用,如果没有正常连接启用则使用本地缓存管理。 Redis缓存管理对于类型具有特别的要求,对于不同的数据类型需要使用对应的类型进行保存。且不允许使用复杂的对象类型进行保存,如list-object是不被允许的,需要转换为list-string的类型再进行保存,同理Map类型也不被允许使用Object,但是单个JavaBean是允许进行存取的。即redis 缓存管理不支持三维结构存储,仅支持二维结构存储。 Redis缓存管理的数据会有简易的持久化。即当redis停止后或者系统停止后,再次启动时redis 依然存有数据提供,不需要再次载入缓存。如果缓存设置了失效则可能会被清除。 Redis缓存管理保存、修改 由于redis数据类型的特殊性,所以所有Java中复杂的对象存储都需要进行相应的转换后才可

Ehcache是现在最流行纯Java开源缓存框架

Ehcache是现在最流行的纯Java开源缓存框架 2014-12-22 13:28 37723人阅读评论(0) 收藏举报分类: java(405) c:\t _blank Ehcache是现在最流行的纯Java开源缓存框架,配置简单、结构清晰、功能强大,最初知道它,是从hibernate的缓存开始的。网上中文的EhCache材料以简单介绍和配置方法居多,如果你有这方面的问题,请自行google;对于API,官网上介绍已经非常清楚,请参见官网;但是很少见到特性说明和对实现原理的分析,因此在这篇文章里面,我会详细介绍和分析EhCache的特性,加上一些自己的理解和思考,希望对缓存感兴趣的朋友有所收获。 一、特性一览,来自官网,简单翻译一下: 1、快速轻量 过去几年,诸多测试表明Ehcache是最快的Java缓存之一。 Ehcache的线程机制是为大型高并发系统设计的。 大量性能测试用例保证Ehcache在不同版本间性能表现得一致性。 很多用户都不知道他们正在用Ehcache,因为不需要什么特别的配置。 API易于使用,这就很容易部署上线和运行。 很小的jar包,Ehcache 2.2.3才668kb。 最小的依赖:唯一的依赖就是SLF4J了。 2、伸缩性 缓存在内存和磁盘存储可以伸缩到数G,Ehcache为大数据存储做过优化。 大内存的情况下,所有进程可以支持数百G的吞吐。 为高并发和大型多CPU服务器做优化。 线程安全和性能总是一对矛盾,Ehcache的线程机制设计采用了Doug Lea的想法来获得较高的性能。 单台虚拟机上支持多缓存管理器。

通过Terracotta服务器矩阵,可以伸缩到数百个节点。 3、灵活性 Ehcache 1.2具备对象API接口和可序列化API接口。 不能序列化的对象可以使用除磁盘存储外Ehcache的所有功能。 除了元素的返回方法以外,API都是统一的。只有这两个方法不一致:getObjectValue和getKeyValue。这就使得缓存对象、序列化对象来获取新的特性这个过程很简单。 支持基于Cache和基于Element的过期策略,每个Cache的存活时间都是可以设置和控制的。 提供了LRU、LFU和FIFO缓存淘汰算法,Ehcache 1.2引入了最少使用和先进先出缓存淘汰算法,构成了完整的缓存淘汰算法。 提供内存和磁盘存储,Ehcache和大多数缓存解决方案一样,提供高性能的内存和磁盘存储。 动态、运行时缓存配置,存活时间、空闲时间、内存和磁盘存放缓存的最大数目都是可以在运行时修改的。 4、标准支持 Ehcache提供了对JSR107 JCACHE API最完整的实现。因为JCACHE在发布以前,Ehcache的实现(如net.sf.jsr107cache)已经发布了。 实现JCACHE API有利于到未来其他缓存解决方案的可移植性。 Ehcache的维护者Greg Luck,正是JSR107的专家委员会委员。 5、可扩展性 监听器可以插件化。Ehcache 1.2提供了CacheManagerEventListener和CacheEventListener接口,实现可以插件化,并且可以在ehcache.xml里配置。 节点发现,冗余器和监听器都可以插件化。 分布式缓存,从Ehcache 1.2开始引入,包含了一些权衡的选项。Ehcache的团队相信没有什么是万能的配置。 实现者可以使用内建的机制或者完全自己实现,因为有完整的插件开发指南。 缓存的可扩展性可以插件化。创建你自己的缓存扩展,它可以持有一个缓存的引用,并且绑定在缓存的生命周期内。 缓存加载器可以插件化。创建你自己的缓存加载器,可以使用一些异步方法来加载数据到缓存里面。 缓存异常处理器可以插件化。创建一个异常处理器,在异常发生的时候,可以执行某些特定操作。

Redis面试题及答案

Redis 是一个基于内存的高性能key-value数据库。(有空再补充,有理解错误或不足欢迎指正) Reids的特点 Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。 因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过10万次读写操作,是已知性能最快的Key-Value DB。 Redis的出色之处不仅仅是性能,Redis最大的魅力是支持保存多种数据结构,此外单个value的最大限制是1GB,不像 memcached只能保存1MB的数据,因此Redis可以用来实现很多有用的功能,比方说用他的List来做FIFO双向链表,实现一个轻量级的高性能消息队列服务,用他的Set可以做高性能的tag系统等等。 另外Redis也可以对存入的Key-Value设置expire时间,因此也可以被当作一个功能加强版的memcached来用。 Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。 Redis支持的数据类型 Redis通过Key-Value的单值不同类型来区分, 以下是支持的类型: Strings Lists Sets 求交集、并集 Sorted Set hashes

为什么redis需要把所有数据放到内存中? Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。所以redis具有快速和数据持久化的特征。 如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能。在内存越来越便宜的今天,redis将会越来越受欢迎。 如果设置了最大使用的内存,则数据已有记录数达到内存限值后不能继续插入新值。 Redis是单进程单线程的 redis利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销 虚拟内存 当你的key很小而value很大时,使用VM的效果会比较好.因为这样节约的内存比较大. 当你的key不小时,可以考虑使用一些非常方法将很大的key变成很大的value,比如你可以考虑将key,value组合成一个新的value. vm-max-threads这个参数,可以设置访问swap文件的线程数,设置最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的. 可能会造成比较长时间的延迟,但是对数据完整性有很好的保证. 自己测试的时候发现用虚拟内存性能也不错。如果数据量很大,可以考虑分布式或者其他数据库 分布式 redis支持主从的模式。原则:Master会将数据同步到slave,而slave不会将数据同步到master。Slave启动时会连接master来同步数据。 这是一个典型的分布式读写分离模型。我们可以利用master来插入数据,slave提供检索服务。这样可以有效减少单个机器的并发访问数量。

小程序的更新机制

背景 此前我们有收到开发者的反馈,当小程序发布新版本后,新版本覆盖率比较慢,尤其是遇到 了一些紧急的 BUG时,线上覆盖速度令人着急。 为了解决这个问题,我们进行了一些探索,最终得出了一个解决方案——小程序更新机制, 今天和大家分享一下。 小程序的更新机制 异步更新机制 小程序的更新需要经过两个关键的步骤: Step1:向微信后台请求新版本信息; Step2:从微信 CDN 下载小程序的代码包。 这两个步骤均需要网络链接,同时这两个步骤都是单独进行,并且是强依赖的,即如果没有 新版本信息,就无法确定新版本的下载地址。 更新检测与下载流程通常会放在启动阶段进行,小程序平台也是如此。 不过小程序的更新流程与启动流程是同时并发执行。 即使更新信息拉取失败了,也不会影响小程序的启动;同时更新也不会影响到小程序的启动 速度。 但由于小程序的更新流程是异步的,无法在本次启动就能够应用上新的版本,如果本次启动 已经下载好新的版本了,需要在下次启动小程序时才能应用上新版本。 超过有效时间强制同步更新机制 为了尽量避免这种更新延迟情况,我们还设计了一个超过有效时间同步检查更新机制,假如 用户已经超过7天没有打开过小程序了,这个时候会强制同步拉取新版本信息、下载新版本,并且使用新版本启动。 更新机制引起的问题 超过有效时间同步检查更新机制能确保到发布版本7天后,绝大部分用户能用上新的版本, 但问题时在 7天之内使用的用户,可能在第一次启动时遇到的是异步更新机制,需要在第二 次启动时才能应用新的版本。 这就导致了一些紧急发布无法在批量检查更新的 7天内无法覆盖到绝大部分用户,对于线上 问题来说是很致命的。 解决这一问题的思路 为了解决这个问题,我们内部也经历了数个方案的讨论,与大家分享一下我们思考的过程:1. 同步检查更新(放弃) 可能是最直接的解决思路,但这个方案的问题在于会影响小程序的启动速度,当下小程序的 更新迭代是非常频繁的,部分用户可能每次启动都命中更新,如果需要同步检查更新 + 同步 下载新的版本,那将会影响这部分用户的启动体验。 2. 模块热替换(放弃) 模块热替换是指小程序运行起来后,将新版本的 JS 代码与页面进行热替换,使之可以在当前版本上应用上新版本的功能。 这种方案可以解决异步更新不能在本次启动马上应用上的问题,从技术上来说,这也是最好 的方案,但同时缺点也比较明显,会存在新旧逻辑、页面共存问题,对于开发者来说,反而 更不好处理,特别是涉及到全局变量时,情况会更复杂。

高并发网站多级缓存设计

高并发网站多级缓存设计

什么是多级缓存 所谓多级缓存,即在整个系统架构的不同系统层级进行数据缓存,以提升访问效率,这也是应用最广的方案之一。我们应用的整体架构如图1所示: 图1 多级缓存方案 整体流程如上图所示: 1)首先接入Nginx将请求负载均衡到应用Nginx,此处常用的负载均衡算法是轮询或者一致性哈希,轮询可以使服务器的请求更加均衡,而一致性哈希可以提升应用Nginx的缓存命中率,相对于轮询,

一致性哈希会存在单机热点问题,一种解决办法是热点直接推送到接入层Nginx,一种办法是设置一个阀值,当超过阀值,改为轮询算法。 2)接着应用Nginx读取本地缓存(本地缓存可以使用Lua Shared Dict、Nginx Proxy Cache(磁盘/内存)、Local Redis实现),如果本地缓存命中则直接返回,使用应用Nginx本地缓存可以提升整体的吞吐量,降低后端的压力,尤其应对热点问题非常有效。 3)如果Nginx本地缓存没命中,则会读取相应的分布式缓存(如Redis缓存,另外可以考虑使用主从架构来提升性能和吞吐量),如果分布式缓存命中则直接返回相应数据(并回写到Nginx本地缓存)。 4)如果分布式缓存也没有命中,则会回源到Tomcat集群,在回源到Tomcat集群时也可以使用轮询和一致性哈希作为负载均衡算法。 5)在Tomcat应用中,首先读取本地堆缓存,如果有则直接返回(并会写到主Redis集群),为什么要加一层本地堆缓存将在缓存崩溃与快速修复部分细聊。

6)作为可选部分,如果步骤4没有命中可以再尝试一次读主Redis集群操作。目的是防止当从有问题时的流量冲击。 7)如果所有缓存都没有命中只能查询DB或相关服务获取相关数据并返回。 8)步骤7返回的数据异步写到主Redis集群,此处可能多个Tomcat实例同时写主Redis集群,可能造成数据错乱,如何解决该问题将在更新缓存与原子性部分细聊。 应用整体分了三部分缓存:应用Nginx本地缓存、分布式缓存、Tomcat堆缓存,每一层缓存都用来解决相关的问题,如应用Nginx本地缓存用来解决热点缓存问题,分布式缓存用来减少访问回源率、Tomcat堆缓存用于防止相关缓存失效/崩溃之后的冲击。 虽然就是加缓存,但是怎么加,怎么用细想下来还是有很多问题需要权衡和考量的,接下来部分我们就详细来讨论一些缓存相关的问题。 如何缓存数据

mybatis的缓存机制(一级缓存二级缓存和刷新缓存)和mybatis整合ehcache

mybatis的缓存机制(一级缓存二级缓存和刷新缓存)和 mybatis整合ehcache 1 查询缓存1.1 什么是查询缓存mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。mybaits 提供一级缓存,和二级缓存。一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个(内存区域)数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。一级缓存的作用域是同一个SqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。Mybatis默认开启一级缓存。二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper 的sql语句,多个SqlSession去操作数据库得到数据会存在二级缓存区域,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。二级缓存是多个SqlSession 共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql 中传递参数也相同即最终执行相同的sql语句,第一次执行

完毕会将数据库中查询的数据写到缓存(内存),第二次会 从缓存中获取数据将不再从数据库查询,从而提高查询效率。Mybatis默认没有开启二级缓存需要在setting全局参数中配置开启二级缓存。如果缓存中有数据就不用从数据库中获取,大大提高系统性能。1.2 一级缓存1.2.1 一级缓存工作原理下图是根据id查询用户的一级缓存图解第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的 用户信息,如果没有,从数据库查询用户信息。得到用户信息,将用户信息存储到一级缓存中。如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession 中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。1.2.2 一级缓存测试mybatis默认支持一级缓存,不需要在配置文件去配置。按照上边一级 缓存原理步骤去测试。@Test public void testCache1() throws Exception{ SqlSessionsqlSession = sqlSessionFactory.openSession();//创建代理对象UserMapperuserMapper = sqlSession.getMapper(UserMapper.class); // 下边查询使用一个SqlSession //第一次发起请求,查询id为1的用户Useruser1 =

Java编程提高性能时需注意的地方

Java编程提高性能时需注意的地方 最近的机器内存又爆满了,出了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了。 下面是参考网络资源和总结一些在java编程中尽可能做到的一些地方 1.尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面 第一,控制资源的使用,通过线程同步来控制资源的并发访问 第二,控制实例的产生,以达到节约资源的目的 第三,控制数据共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信 2.尽量避免随意使用静态变量 要知道,当某个对象被定义为stataic变量所引用,那么gc通常是不会回收这个对象所占有的内存,如 1 2 3 public class A{ static B b = new B(); } 此时静态变量b的生命周期与A类同步,如果A类不会卸载,那么b对象会常驻内存, 直到程序终止。 3.尽量避免过多过常的创建java对象 尽量避免在经常调用的方法,循环中new对象,由于系统不仅要花费时间来创建对象,而且还要花时间对这些对象进行垃圾回收和处理,在我们可以控制的范围内,最大限度的重用对象,最好能用基本的数据类型或数组来替代对象。 4.尽量使用final修饰符 带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如https://www.360docs.net/doc/9715829748.html,ng.String。为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。 5.尽量使用局部变量 调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量,实例变量等,都在堆(Heap)中创建,速度较慢。 6.尽量处理好包装类型和基本类型两者的使用场所 虽然包装类型和基本类型在使用过程中是可以相互转换,但它们两者所产生的内存区域是完全不同的,基本类型数据产生和处理都在栈中处理,包装类型是对象,是在堆中产生实例。 在集合类对象,有对象方面需要的处理适用包装类型,其他的处理提倡使用基本类型。

redis-jedis笔记整理

启动Redis服务器 启动客户端 Redis命令目录key(建) 保存键值对set key value 查询指定键对象get key 删除给定键的对象del key1key2…

设置键过期时间EXPIRE key exptime 剩余时间ttl key 查看搜索有键值keys键 migrate指令(移动将数据移动另外一个数据) 将key原子性地从当前实例传送到目标实例的指定数据库上,一旦传送成功,key保证会出现在目标实例上,而当前实例上的key会被删除。 MOVE key db 将数据库的key移动到指定的数据库db当中。如果当前数据库(源数据库)和给定数据库(目标数据库)有相同的名字的给定key,或者key不存在于当前数据库,那么MOVE没有任何效果。因此,也可以利用这一特性,将MOVE当作锁(locking)原语(primitive)。

Obejct{refcount|encoding|idletime} 通常用在debug或者了解为了节省空间使用特殊的编码情况,当redis用作缓存时候,也可以通过OBJECT命令中的信息,决定key的驱逐策略. object refcount key:返回给定key引用所存储的值的次数. object encoding key:返回给定key所存储的值编码可以有 raw(一般字符串)或int(用字符串表示64位数字是为了节约空间)。 ziplist或linkedlist。ziplist是为节约大小较小的列表空间而作的特殊表示。 intset或者hashtable。intset是只储存数字的小集合的特殊表示。 zipmap或者hashtable。zipmap是小哈希表的特殊表示。 ziplist或者skiplist格式。ziplist用于表示小的有序集合,而skiplist则用于表 示任何大小的有序集合。 object idletime key:返回给定key自存储的空闲时间 persist key 将key从带生存时间转换为持久的不带生存时间.

相关文档
最新文档