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

本人菜鸟一名,刚毕业出来没多久,在上海一家公司工作,公司有算上我有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>


 


   <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个区别是我的切身体会,还有很多区别在这里就不一一说明了,在网上都可以查到。


本人菜鸟一枚,大神勿喷,以上只是本人学习的一点小体会,也只是懂了点皮毛,也有很多不懂得地方,希望可以和你们一起交流,共同进步。


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值