ssm+redis cluster集群

1、简介

redis cluster是去中心化,去中间件的,也就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。

Redis 集群没有并使用传统的一致性哈希来分配数据,而是采用另外一种叫做哈希槽 (hash slot)的方式来分配的。redis cluster 默认分配了 16384 个slot,当我们set一个key 时,会用CRC16算法来取模得到所属的slot,然后将这个key 分到哈希槽区间的节点上,具体算法就是:CRC16(key) % 16384

redis cluster 为了保证数据的高可用性,加入了主从模式,一个主节点对应一个或多个从节点,主节点提供数据存取,从节点则是从主节点拉取数据备份,当这个主节点挂掉后,就会有这个从节点选取一个来充当主节点,从而保证集群不会挂掉。


2、搭建集群

首先去官方下载Redis,我这里下载的是3.0.5版本 
1.解压

[root@spg redis-claster]# tar -zxvf redis-3.0.5.tar.gz

2.安装

[root@spg redis-claster]#cd redis-3.0.5

[root@spg redis-3.0.5]#make && make install

3.将redis-trib.rb 复制到/usr/local/bin

[root@spg redis-3.0.5]#cp src/redis-trib.rb /usr/local/bin

4.开始集群搭建,首先修改配置文件。

[root@spg redis-3.0.5]#vi redis.conf

修改如下几处:

port 7000

cluster-enabled yes

cluster-config-file nodes.conf

cluster-node-timeout 5000

appendonly yes

5、新建6个节点(注意:Redis Cluster要求至少6个节点,3主3备,否则构建集群会报错):

#这里文件名就按端口号命名,方便区分。

 [root@spg redis-claster]# mkdir 7000 

[root@spg redis-claster]# mkdir 7001 

[root@spg redis-claster]# mkdir 7002 

[root@spg redis-claster]# mkdir 7003

 [root@spg redis-claster]# mkdir 7004 

[root@spg redis-claster]# mkdir 7005

 

6、redis.conf 分别拷贝到这6个文件夹中,并修改其中对应的端口号。 
分别启动6个Redis。

[root@spg redis-claster]# cd 7000 

[root@spg 7000]# redis-server redis.conf & 

#其他几个启动略...

 

7、查看进程查看各redis是否已经正常启动

[root@spg redis-claster]# ps -ef | grep redis

 

8、6个Redis加入集群

需要用到的命令就是redis-trib.rb,这是官方的一个用ruby写的一个操作redis cluster的命令,所以,你的机器上需要安装ruby。我们先试一下这个命令:

#redis-trib.rb create --replicas 1 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

 

因为我们要新建集群, 所以这里使用create命令. –replicas 1 参数表示为每个主节点创建一个从节点. 其他参数是实例的地址集合。

由于我机子上没安装ruby,所以,会报错:

/usr/bin/env: ruby: 没有那个文件或目录

命令安装ruby:

[root@spg 7003]# yum install ruby ruby-devel rubygems rpm-build

完成后继续执行,结果还是报错:

[root@spg 7003]# redis-trib.rb create --replicas 1 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

/usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- redis (LoadError)    from /usr/share/rubygems/rubygems/core_ext/kernel_require.rb:55:in `require'    from /usr/local/bin/redis-trib.rb:25:in `<main>'

这是因为ruby和redis的连接没安装好:

[root@spg 7003]# gem install redis 

Fetching: redis-3.2.2.gem (100%)

Successfully installed redis-3.2.2 

Parsing documentation for redis-3.2.2 

Installing ri documentation for redis-3.2.2 1 gem installed

安装完后再创建集群

[root@spg redis-claster]# redis-trib.rb create --replicas 1 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 

>>> Creating cluster

Connecting to node 127.0.0.1:7000: OK

Connecting to node 127.0.0.1:7001: OK

Connecting to node 127.0.0.1:7002: OK

Connecting to node 127.0.0.1:7003: OK

Connecting to node 127.0.0.1:7004: OK

Connecting to node 127.0.0.1:7005: OK

>>> Performing hash slots allocation on 6 nodes...

Using 3 masters: 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002

 

9、检查集群各节点状态:

[root@spg redis-3.0.5]# redis-trib.rb check 127.0.0.1:7000

Connecting to node 127.0.0.1:7000: OK 

Connecting to node 127.0.0.1:7002: OK 

Connecting to node 127.0.0.1:7004: OK 

Connecting to node 127.0.0.1:7005: OK 

Connecting to node 127.0.0.1:7001: OK 

Connecting to node 127.0.0.1:7003: OK 

>>> Performing Cluster Check (using node 127.0.0.1:7000)

,,,,,,,,

 

10、测试集群链接状况

redis-cli是redis默认的客户端工具,启动时加上`-c`参数,就可以连接到集群。 连接任意一个节点端口:

[root@spg 7006]# redis-cli -c -p 7003 

127.0.0.1:7003>set my_name wind

-> Redirected to slot [12803] located at 127.0.0.1:7002 OK

127.0.0.1:7002>get my_name

"wind"

2、java连接测试

import java.util.HashSet; 
import java.util.Set; 
import redis.clients.jedis.HostAndPort; 
import redis.clients.jedis.JedisCluster; 
/** * Jedis集群测试 * *
 @author Switch 
* @data 2017年2月11日 
* @version V1.0 
*/ 
public class JedisClusterTest { 
public static void main(String[] args) { 
// 创建并填充节点信息 
Set<HostAndPort> nodes = new HashSet<>(); 
nodes.add(new HostAndPort("192.168.37.131", 7001)); 
nodes.add(new HostAndPort("192.168.37.131", 7002)); 
nodes.add(new HostAndPort("192.168.37.131", 7003)); 
nodes.add(new HostAndPort("192.168.37.131", 7004)); 
nodes.add(new HostAndPort("192.168.37.131", 7005)); 
nodes.add(new HostAndPort("192.168.37.131", 7006)); 
// 创建JedisCluster对象 
JedisCluster jedisCluster = new JedisCluster(nodes); 
// 使用jedisCluster操作redis 
String key = "jedisCluster"; 
String setResult = jedisCluster.set(key, "hello redis!"); System.out.println(setResult); 
String getResult = jedisCluster.get(key); System.out.println(getResult); 
// 关闭jedisCluster(程序执行完后才能关闭,内部封装了连接池) jedisCluster.close(); 
} 
}

2、SSM + redis cluster项目实战

1)加入jar

版本匹配:

redis.client  2.9.0 ---- spring-data-redis  1.7.1.RELEASE 

   redis.client 2.9.0 -----spring-data-redis   1.7.2.RELEASE

由于版本不匹配,遇到的错误如下:

1. ClassNotFoundException  : redis/client/util/geoUtils   

说这个类找不到。

  2. org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisTemplate' defined in class path resource [applicationContext.xml]

   说创建 redisTemplate bean 对象时失败了。

 

2maven pom.xml 文件
<dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.9.0</version>
  </dependency>
    <!-- spring-data-redis 依赖-->
<dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>1.7.1.RELEASE</version>
    </dependency>
<!--  排除slf日志-->
<exclusions>
			<exclusion>
				<groupId>org.slf4j</groupId>
				<artifactId>slf4j-api</artifactId>
			</exclusion>
		</exclusions> //这里为什么要排除slf日志?因为我的框架使用的是log4j,如果有slf,那么log4j的日志将不生效。所以要排除。因为spring-data-redis依赖slf。这 样的缺点spring-data-redis的日志就输出不了了
2)配置redis-conf.properties

#JedisPoolConfig的参数
#最大连接数
redis.pool.maxTotal=30
#最大空闲时间
redis.pool.maxIdle=10
#每次最大连接数
redis.pool.numTestsPerEvictionRun=1024
#释放扫描的扫描间隔
redis.pool.timeBetweenEvictionRunsMillis=30000
#连接的最小空闲时间
redis.pool.minEvictableIdleTimeMillis=1800000
#连接控歘按时间多久后释放,当空闲时间>该值且空闲连接>最大空闲连接数时直接释放
redis.pool.softMinEvictableIdleTimeMillis=10000
#获得链接时的最大等待毫秒数,小于0:阻塞不确定时间,默认-1
redis.pool.maxWaitMillis=1500
#在获得链接的时候检查有效性,默认false
redis.pool.testOnBorrow=true
#在空闲时检查有效性,默认false
redis.pool.testWhileIdle=true
#连接耗尽时是否阻塞,false报异常,true阻塞超时,默认true
redis.pool.blockWhenExhausted=false
#RedisClusterConfiguration配置
redis.maxRedirects=3
#主机和端口号
redis.host=192.168.48.131
redis.port=6379
redis.host2=192.168.48.131
redis.port2=6380
redis.host3=192.168.48.131
redis.port3=6381
redis.host4=192.168.48.131
redis.port4=6382
redis.host5=192.168.48.131
redis.port5=6383
redis.host6=192.168.48.131
redis.port6=6384

3) 配置redis 配置文件 我把它单独提取出来放在一个配置文件(spring-data-redis-cluster.xml)中,然后import spring ApplicationContext.xml 文件中

说明:这里边的引用值不是redis-conf.properties文件中的,若想使用直接在里边修改即可。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:task="http://www.springframework.org/schema/task" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xsi:schemaLocation="
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
    http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
    http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">

<!--  redis连接池  这里引用的是jedis 包中的功能  -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal" value="${redis.maxActive:1024}" />
<property name="maxIdle" value="${redis.maxIdle:1024}" />
<property name="maxWaitMillis" value="${redis.maxWait:10000}" />
<property name="testOnBorrow" value="${redis.testOnBorrow:true}" />
<property name="testOnReturn" value="${redis.testOnReturn:true}" />
</bean>

<!-- Redis集群配置     这里使用的是spring-data-redis  包中内容 -->
<bean id="redisClusterConfig" class="org.springframework.data.redis.connection.RedisClusterConfiguration">
        <property name="maxRedirects" value="6"></property>
        <property name="clusterNodes">
            <set>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.105"></constructor-arg>
                    <constructor-arg name="port" value="7111"></constructor-arg>
                </bean>

                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.105"></constructor-arg>
                    <constructor-arg name="port" value="7112"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.105"></constructor-arg>
                    <constructor-arg name="port" value="7116"></constructor-arg>
                </bean>
                <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.102"></constructor-arg>
                    <constructor-arg name="port" value="7113"></constructor-arg>
                </bean>
                 <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.102"></constructor-arg>
                    <constructor-arg name="port" value="7114"></constructor-arg>
                </bean>
                 <bean class="org.springframework.data.redis.connection.RedisNode">
                    <constructor-arg name="host" value="192.168.1.102"></constructor-arg>
                    <constructor-arg name="port" value="7115"></constructor-arg>
                </bean>
            </set>
        </property>
    </bean> 
    <!-- Redis连接工厂     -->
    <bean id="redis4CacheConnectionFactory"
        class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <constructor-arg name="clusterConfig" ref="redisClusterConfig" />
        <property name="timeout" value="${redis.timeout:10000}" />
        <property name="poolConfig" ref="jedisPoolConfig" />
    </bean>
    <!-- 存储序列化 -->
    <bean name="stringRedisSerializer"
        class="org.springframework.data.redis.serializer.StringRedisSerializer" />

    <!-- 集群Resis使用模板 -->
    <bean id="clusterRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
        <property name="connectionFactory" ref="redis4CacheConnectionFactory" />
        <property name="keySerializer" ref="stringRedisSerializer" />
        <property name="hashKeySerializer" ref="stringRedisSerializer" />
        <property name="valueSerializer" ref="stringRedisSerializer" />
        <property name="hashValueSerializer" ref="stringRedisSerializer" />
    </bean>
</beans>
4ApplicationContent.xml 配置文件中 导入以上配置

<!-- 导入rediscluster配置文件 -->
<import resource="classpath:spring-data-redis-cluster.xml" />

5)redisTemplate  的应用

自定义一个redisClient类来管理操作 redis 的存取操作

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
@Service
public class RedisClusterClient {
        // 由于在Spring ApplicationContext.xml 配置文件中导入了 redis的配置文件,也就间接的将 <bean id="clusterRedisTemplate"                                                                  class="org.springframework.data.redis.core.RedisTemplate">  这个Bean托管给了Spring bean容器来管理所以 只要我使用注解就可以把这个模板类对象引用过来。
       @Autowired
       private RedisTemplate<String,String> clusterRedisTemplate;
     
       //添加数据
        public void put(Object key, Object value) {
            if(null == value) {
                return;
            }
     
            if(value instanceof String) {
                if(StringUtils.isEmpty(value.toString())) {
                    return;
                }
            }
     
            // TODO Auto-generated method stub
            final String keyf = key + "";
            final Object valuef = value;
            final long liveTime = 86400;
     
            clusterRedisTemplate.execute(new RedisCallback<Long>() {
                public Long doInRedis(RedisConnection connection)
                        throws DataAccessException {
                    byte[] keyb = keyf.getBytes();
                    byte[] valueb = toByteArray(valuef);
                    connection.set(keyb, valueb);
                    if (liveTime > 0) {
                        connection.expire(keyb, liveTime);
                    }
                    return 1L;
                }
            });
        }
     
         // 获取数据
        public Object get(Object key) {
            final String keyf = (String) key;
            Object object;
            object = clusterRedisTemplate.execute(new RedisCallback<Object>() {
                public Object doInRedis(RedisConnection connection)
                        throws DataAccessException {
     
                    byte[] key = keyf.getBytes();
                    byte[] value = connection.get(key);
                    if (value == null) {
                        return null;
                    }
                    return toObject(value);
     
                }
            });
     
            return object;
        }
     
        /**
         * 描述 : <byte[]转Object>. <br>
         * <p>
         * <使用方法说明>
         * </p>
         *
         * @param bytes
         * @return
         */
        private Object toObject(byte[] bytes) {
            Object obj = null;
            try {
                ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
                ObjectInputStream ois = new ObjectInputStream(bis);
                obj = ois.readObject();
                ois.close();
                bis.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            } catch (ClassNotFoundException ex) {
                ex.printStackTrace();
            }
            return obj;
        }
     
        private byte[] toByteArray(Object obj) {
            byte[] bytes = null;
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            try {
                ObjectOutputStream oos = new ObjectOutputStream(bos);
                oos.writeObject(obj);
                oos.flush();
                bytes = bos.toByteArray();
                oos.close();
                bos.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            return bytes;
        }
    
}
实现:

controller层:原来怎么写不动;

在service层:进行业务处理时,比如查询商品信息时先从redis中查找,若没有就从数据库中查找,查找后把数据对象放到redis缓存中,方便下次快速查找。



【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 3、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于ssm+shiro+redis+nginx tomcat服务器集群管理项目源码+项目说明.zip Introduction ==== 1.搭建一个最简洁,模块划分最明确的ssm+swargger+shiro+redis+nginx整合项目,采用maven作为构建工具,在有新项目开发时可以借助此demo快速构建项目<br/> 2.实现shiro的授权信息缓存到redis数据库,减少关系数据库访问压力<br/> 3.实现session共享到redis,实现多服务器集群方案<br/> 4.配置文档中包含丰富的注释,搭建思路清晰的ssm项目框架<br/> 5.项目中的所有细节都会按照企业级开发的标准,展示如何遵循代码规范以及类文件doc注释的编写。<br/> 6.采用RESTFul的controller接口,展示RESTFul风格的API编写(shiro基于url的权限拦截与RESTFul API兼容性不好,后期可能会改写shiro以匹配RESTFul)<br/> 7.Junit单元测试,展示如何正确的使用Junit单元测试验证自己接口代码的健壮性<br/> 涉及到的技术 ==== springmvc+spring+mybatis:轻量级敏捷开发框架<br/> swargger:快速构建RestFul接口测试页面<br/> shiro:Apache开源权限管理框架,包括登录验证,授权,加密,会话管理<br/> redis:Nosql数据库,搭配shiro的会话管理功能将session存入redis中,实现tomcat多服务器集群的session共享<br/> nginx:反向代理服务器,用来调度多台tomcat<br/> h2:内存数据库,用于测试<br/> 开发环境 ==== jdk1.8+mysql5.7.22+tomcat8.5.32+IDEA<br/> 项目部署 ==== 第一次部署项目<br/> 1.修改ssm-rs\resources目录下db.properties的数据库账号密码信息<br/> 2.启动redis服务端,修改ssm-rs\resources\spring-config目录下spring-shiro.xml中redis的连接信息,没设置密码的话auth留空<br/> 2.创建数据库train_db并执行根目录下的train_db.sql数据库脚本<br/> 3.进入到ssm-build目录下,执行clean install -Dmaven.test.skip=true,对整个项目进行构建<br/> 4.启动ssm-rs项目,浏览器访问http://localhost/ssm-rs/swagger-ui.html<br/> 项目模块 ==== ssm-build <br/> 项目聚合模块,可以进入该项目目录,对整个项目进行构建。<br/> mvn clean install -Dmaven.test.skip=true <br/> ssm-parent<br/> 父模块,其他模块会继承该模块,引入公共的依赖<br/> ssm-model<br/> 模型层模块,提供各种POJO。包括与数据库表对应的模型、传输模型等。提供给service层(ssm-cs)、controller层(ssm-rs)。<br/> ssm-commons<br/> 包含各种工具类<br/> ssm-cs<br/> service层和dao层,提供具体的业务逻辑和数据库访问,需要依赖ssm-model模块,并提供出来给ssm-rs模块调用<br/> ssm-rs<br/> controller层,提供RESTFul接口。<br/>
随着互联网应用的快速发展,Java EE成为当下互联网开发中最为流行的开发语言之一。而在Java EE开发中,轻量级框架的整合是必不可少的一部分。其中SSM框架是最先被广泛应用的一种框架,它是由Spring、SpringMVC和MyBatis三个框架整合而成。此外,Spring框架也是Java EE开发中非常重要的一部分,它主要提供了全部企业级应用的核心技术和API,包括依赖注入、控制反转等。 对于如何提高web应用的性能,Redis是一个非常强大的缓存解决方案。它是一种内存数据存储系统,能提供快速读取数据、支持分布式和高可用性等特性。当然,Redis的应用需要和Java EE整合,才能更好地发挥其功能。 最近几年,微服务架构也成为Java EE中非常关注的技术趋势。微服务架构是一种面向服务的架构,它将一个应用程序拆分成若干个服务,这些服务之间通过API方式进行互相通信。微服务架构可以执行部署,提高应用可扩展性,从而更好地满足应用程序的要求和需求。 最后,在Java EE开发中,PDF文档的生成和处理也是一个非常重要的任务。开发人员可以使用PDF框架来生成各种类型的PDF文档,满足企业应用的需求和要求。 总的来说,以上几种Java EE互联网轻量级框架整合开发技术都非常重要,可以提高应用程序的开发效率和可用性,同时也能提高web应用程序在互联网中的性能和可扩展性,提供更好的用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值