您的位置:首页 > 数据库 > Memcache

spring data redis 集群(sentinel实现)和simple spring memcached分布式初使用

2015-07-16 14:53 861 查看
本人菜鸟一名,刚毕业出来没多久,在上海一家公司工作,公司有算上我有3个java程序员,其他两个有两到三年的工作经验,他们负责APP的接口开发,我一个人负责后台管理接口开发,公司项目框架是用Spring搭建的,开发工具也是Spring的,持久层集成了Spring data jap和Mybatis,控制层用的是Spring MVC ,对于刚出校园的我来说觉得这框架塔的特别牛。由于项目的权限做的有点复杂,而且查询的地方特别多,网页加载速度特别慢,老大说把那些权限判断放我缓存里,让我去做,我当时就楞住了,我刚从学校出来,只知道hibernate二级缓存,老大让我在memcached和redis中选一个,还要做集群模式的,我那时还是试用期,为了突显自己的能力,就硬着头皮答应下来了。现在就写下我学习这两个缓存的路程。

redis sentinel 介绍:(此处copy)

Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance),该系统执行以下三个任务:

监控(Monitoring):Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
提醒(Notification):当被监控的某个 Redis 服务器出现问题时,Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
自动故障迁移(Automatic failover):当一个主服务器不能正常工作时,Sentinel 会开始一次自动故障迁移操作,它会将失效主服务器的其中一个从服务器升级为新的主服务器,并让失效主服务器的其他从服务器改为复制新的主服务器;当客户端试图连接失效的主服务器时,集群也会向客户端返回新主服务器的地址,使得集群可以使用新主服务器代替失效服务器。

首先介绍redis sentinel服务端配置

这是端口号为6479的redis主服务器

##redis.conf

##redis-0,默认为def_master 

port 6479

##授权密码,请各个配置保持一致

requirepass 123456

masterauth 123456

##暂且禁用指令重命名

##rename-command

##开启AOF,禁用snapshot

appendonly yes

save 900 1

save 300 10

save 60 10000

##slaveof no one

slave-read-only yes

这是端口号为6480的从服务器

##redis.conf

##redis-0,默认为def_master 

port 6480

slaveof 127.0.0.1 6479

##授权密码,请各个配置保持一致

requirepass 123456

masterauth 123456

##暂且禁用指令重命名

##rename-command

##开启AOF,禁用snapshot

appendonly yes

save 900 1

save 300 10

save 60 10000

##slaveof no one

slave-read-only yes

这是sentinel 集群管理器sentinel.conf配置

##redis-0  

##sentinel实例之间的通讯端口  

port 26379  

##指定sentinel使用的端口,不能与redis-server运行实例的端口冲突,1表示至少一台从服务器发现主服务器故障就会自动主从切换

sentinel monitor def_master 127.0.0.1 6479 1  

##连接redis服务密码

sentinel auth-pass def_master 123456 

##表示如果5s内mymaster没响应,就认为主服务器发生故障

sentinel down-after-milliseconds def_master 50000   

##表示如果master重新选出来后,其它slave节点能同时并行从新master同步缓存的台数有多少个,显然该值越大,所有slave节点完成同步切换的整体速度越快,但如果此时正好有人在访问这些slave,可能造成读取失败,影响面会更广。最保定的设置为1,只同一时间,只能有一台干这件事,这样其它slave还能继续服务,但是所有slave全部完成缓存更新同步的进程将变慢。

sentinel parallel-syncs def_master 1  

表示如果90秒后,mysater仍没活过来,则启动failover(故障转移),从剩下的slave中选一个升级为master

sentinel failover-timeout def_master 900000  

配置写好后就开始启动reids服务,我这是在Windows环境下测试的,在linux下命令有所不同。

输入cmd命令进入控制台,

打开redis文件位置,输入redis-server.exe redis6479.conf启动reids主服务器。

然后打开从服务器位置,输入redis-server.exe redis6480.conf启动reids从服务器。

然后启动sentinel,打开文件位置输入redis-server sentinel.conf  --sentinel启动管理器。

完了之后服务端就开启成功。

一下是客户端连接服务端代码编写:

Spring提供了Spring data redis这个子项目,本人用的就是Spring data redis

spring的配置文件:

spring-data-redis.xml

<?xml version="1.0" encoding="UTF-8"?>  

<beans  

 xmlns="http://www.springframework.org/schema/beans"

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xmlns:context="http://www.springframework.org/schema/context"

 xmlns:p="http://www.springframework.org/schema/p" 

 xmlns:c="http://www.springframework.org/schema/c" 

 xmlns:cache="http://www.springframework.org/schema/cache"

 xmlns:aop="http://www.springframework.org/schema/aop"

 xmlns:tx="http://www.springframework.org/schema/tx" 

 xsi:schemaLocation="http://www.springframework.org/schema/beans 

                    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context-3.2.xsd
                    http://www.springframework.org/schema/aop
                    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 

                   http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
                   

    <context:component-scan base-package="org.tht.service"/>

 

  <cache:annotation-driven></cache:annotation-driven>

 

     <bean id="redisSentinelConfiguration"

        class="org.springframework.data.redis.connection.RedisSentinelConfiguration">

<!--这里的def_master就是集群管理器的名字,我们在客户端只需连接sentinel,sentinel会帮我们去管理redis服务器 -->

        <property name="def_master ">

            <bean class="org.springframework.data.redis.connection.RedisNode">

                <property name="name" value="mymaster"></property>

            </bean>

        </property>

        <property name="sentinels">

            <set>

                  <bean class="org.springframework.data.redis.connection.RedisNode">

                    <constructor-arg name="host" value="127.0.0.1"/>

                    <constructor-arg name="port" value="26379"/>               

                </bean>

            </set>

        </property>

   </bean>

   <bean id="jeidsConnectionFactory"

   class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="password" value="123456"></property>

      <constructor-arg ref="redisSentinelConfiguration"/>

   </bean>
4000

 

   <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"

      p:connection-factory-ref="jeidsConnectionFactory"/>

      

      <bean

        id="cacheManager"

        class="org.springframework.data.redis.cache.RedisCacheManager"

        c:template-ref="redisTemplate"/>

      

    </beans>

  

现在我们写方法:

   @Cacheable(value="messageCache",key="#name")

    public String getMessage(String name) {

       

        return userService.findByName(name);

    }

这是查询方法,@Cacheable(value="messageCache",key="#name")

这个注解是查询redis缓存,value:命名空间,key:返回数据对应的键。如果缓存中没有这个key就会去查询数据库,并将返回的值存入redis,有则直接从缓存中读取数据。

//更新缓存

@CachePut(value="messageCache",key="#name")
public String updateMessage(String name) {

       

      return userService.findByName(name);

    }

这个注解是修改redis缓存@CachePut(value="messageCache",key="#name")

//清空命名空间为messageCache下的所有缓存
@CacheEvict(value="messageCache",allEntries=true)
public void deleteOperationAuthByPageUrlCache() {

}

//清空命名空间为messageCache下key为name的缓存
@CacheEvict(value="messageCache",allEntries=true,key="#name")
public void deleteOperationAuthByPageUrlCache() {

}

以上代码经过本人测试过,没问题,当主服务器发生故障时从服务器会自动升为主服务器,两台redis服务器的数据会同步,这种集群模式无需担心服务器挂掉之后数据的丢失。

在学校redis之前本人也学习了memcached,之说以选择redis下面会说明原因。

以下是memcached基于客户端分布式代码:

谷歌提供了memcached与Spring集成的组件simple spring memcached,一下是spring-memcache.xml配置

<?xml version="1.0" encoding="UTF-8"?>  

<beans  

  xmlns="http://www.springframework.org/schema/beans"

 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 xmlns:context="http://www.springframework.org/schema/context"

 xmlns:aop="http://www.springframework.org/schema/aop"

 xmlns:tx="http://www.springframework.org/schema/tx" 

 xsi:schemaLocation="http://www.springframework.org/schema/beans 

                    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context-3.2.xsd
                    http://www.springframework.org/schema/aop
                    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
                    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd 

                   ">

  

  <context:component-scan base-package="org.tht.service"/>

  

  <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

  

  <import resource="simplesm-context.xml" />

  <!-- 默认一个client -->

  <bean name="defaultMemcachedClient" class="com.google.code.ssm.CacheFactory">

    <property name="cacheClientFactory">

      <bean name="cacheClientFactory" class="com.google.code.ssm.providers.xmemcached.MemcacheClientFactoryImpl" />

    </property>

    <property name="addressProvider">

      <bean class="com.google.code.ssm.config.DefaultAddressProvider">

<!--服务器地址,在这里实现分布式 -->

        <property name="address" value="127.0.0.1:11211,192.168.1.227:12677" />

      </bean>

    </property>

    <!-- 一致性hash ~。~ -->

    <property name="configuration">

      <bean class="com.google.code.ssm.providers.CacheConfiguration">

        <property name="consistentHashing" value="true" />

      </bean>

    </property>

  </bean>

  <bean class="com.google.code.ssm.Settings">
<property name="order" value="500" />

  </bean>

</beans>  

一下是方法:

 /** 

     * 当执行getUserById查询方法时,系统首先会从缓存中获取id对应的实体 

     * 如果实体还没有被缓存,则执行查询方法并将查询结果放入缓存中 

     */  
@ReadThroughSingleCache(namespace = "test")
 public CacheBean getUserById(@ParameterValueKeyProvider String userId) throws Exception{
   System.out.println("没有缓存命中");
   CacheBean cacheBean=new CacheBean();
cacheBean.setUserId(userId);
cacheBean.setUserName("赵六");
   return cacheBean;
 }

/** 

     * 当执行delete方法时,系统会删除缓存中id对应的实体 

     */ 
@InvalidateSingleCache(namespace="test")
public void delete(@ParameterValueKeyProvider Integer userId){
System.out.println(userId);
}

 /** 

     * 当执行update方法时,系统会更新缓存中id对应的实体 

     * 将实体内容更新成@*DataUpdateContent标签所描述的实体 

     */  
@UpdateSingleCache(namespace="test")
public void update(@ParameterValueKeyProvider @ParameterDataUpdateContent CacheBean cacheBean){
System.out.println(cacheBean.getUserName());
}

现在就开始说说redis和memcached的区别:

在此之前你可能在网上查看了很多关于两者的区别,在此我只说我在用这两个缓存的心得与体会。

区别1:memcached的分布式是基于客户端的(下面会介绍),而redis的分布式是基于服务端的(上面已经写的很清楚了)

区别2:redis可以根据命名空间删除该命名空间下的所有key,而memcached必须得指定key(想删除命名空间下的所有key,只能先将该命名空间下的所有key查出来再进行删除)

区别3:Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而memcached服务器重启后所有缓存数据都会清空。

以上3个区别是我的切身体会,还有很多区别在这里就不一一说明了,在网上都可以查到。

本人菜鸟一枚,大神勿喷,以上只是本人学习的一点小体会,也只是懂了点皮毛,也有很多不懂得地方,希望可以和你们一起交流,共同进步。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  spring data redis 集群