• 搭建Redis集群,Java操作redis(Demo:缓存数据库查询数据,当进行增删改方法时,删除缓存)


    redis-cluster架构图

    架构细节:

    (1)所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽

    (2)节点的fail是通过投票机制即集群中超过半数的节点检测失效时才生效

    (3)客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可

    (4)redis-cluster把所有的物理节点映射到[0-16383]slot上,cluster 负责维护node<->slot<->value

    Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点

    Redis集群的搭建

    搭建资料

    第一步:安装redis

    tar zxvf redis-3.2.5.tar.gz
    
    • 复制:推荐放到usr/local目录下
    sudo mv -r redis-3.2.3/* /usr/local/redis/
    进入redis目录
    cd /usr/local/redis/
    
    • 生成
    sudo make
    
    • 测试
    sudo make test
    这段运行时间会较长,可以略过
    
    • 安装:将redis的命令安装到/usr/bin/目录
    sudo make install

    第二步:搭建伪Redis集群的准备工作

    • 使用命令生成可执行文件到指定目录下(因为需要6个可执行的redis-server)

    sudo make install PREFIX=/usr/local/redis-cluster

    • 将/usr/local/redis目录下的redis.conf文件copy一份到刚生成的目录中,并修改该配置文件

    • 书写脚本运行所有6个redis

    cd redis01
    ./redis-server redis.conf
    cd ..

    第三步:安装ruby和相关的包

    • 安装

     sudo apt-get install ruby

    • 安装redis-3.0.0.gem 

     sudo gem install redis-3.0.0.gem

    • 将/usr/local/redis/src目录下的redis-trib.rb文件copy到任意位置
    •  执行命令运行起来redis集群
    ./redis-trib.rb create --replicas 1 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 127.0.0.1:7006
    真正建立redis集群时,更改为运行redis主机们的ip地址(要关闭防火墙)

    第四步:使用集群

    redis-cli -p 7002 -c  # -c表示操作的是集群

    Java操作redis

    1、导入Jedis包

    <!-- Redis客户端 -->
    <dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    </dependency>

    2、操作redis

    1)直接操作版

    @Test
    public void JedisClient(){
    
        // 1.创建一个Jedis对象。需要指定服务端的ip及端口
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        // 2.使用Jedis对象操作数据库
        jedis.set("k1","v1");
        String k1 = jedis.get("k1");
        System.out.println(k1);
        // 3.关闭Jedis对象
        jedis.close();
    
    }
    

    2)连接池版

    @Test
    public void JedisPool(){
    
        // 1.创建一个JedisPool对象。需要指定服务端的ip及端口
        JedisPool jedisPool = new JedisPool("127.0.0.1", 6379);
        // 2.从JedisPool中获得Jedis对象
        Jedis jedis = jedisPool.getResource();
        // 3.使用Jedis操作redis服务器
        jedis.set("k2","v2");
        String k1 = jedis.get("k2");
        System.out.println(k1);
        // 4.操作完毕后关闭jedis对象,连接池回收资源
        jedis.close();
        // 5.关闭JedisPool对象
        jedisPool.close();
    
    }
    

    3)连接集群版

    @Test
    // 集群默认使用的就是连接池,所以不用我们来配了
    public void JedisCluster(){
    
        // 1.使用JedisCluster对象。需要一个Set<HostAndPort>参数。Redis节点的列表。
        Set<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("127.0.0.1", 7001));
        nodes.add(new HostAndPort("127.0.0.1", 7002));
        nodes.add(new HostAndPort("127.0.0.1", 7003));
        nodes.add(new HostAndPort("127.0.0.1", 7004));
        nodes.add(new HostAndPort("127.0.0.1", 7005));
        nodes.add(new HostAndPort("127.0.0.1", 7006));
    
        // 2.直接使用JedisCluster对象操作redis。在系统中单例存在。
        JedisCluster jedisCluster = new JedisCluster(nodes);
        jedisCluster.set("k3", "v3");
        String result = jedisCluster.get("k3");
        System.out.println(result);
        // 3.系统关闭前,关闭JedisCluster对象。
        jedisCluster.close();
    
    }

    项目整合

    缓存数据库查询数据,当进行增删改方法时,删除缓存;由于我们平时用单机版的就行了,项目发布时在使用集群版,所以我们可以采用面向接口编程;缓存是在service中配置的

     1 public interface JedisClient {
     2 
     3     String set(String key, String value);
     4     String get(String key);
     5     Boolean exists(String key);
     6     Long expire(String key, int seconds);
     7     Long ttl(String key);
     8     Long incr(String key);
     9     Long hset(String key, String field, String value);
    10     String hget(String key, String field);
    11     Long hdel(String key, String... field);
    12     Boolean hexists(String key, String field);
    13     List<String> hvals(String key);
    14     Long del(String key);
    15 }
    Jedis操作的接口
      1 package cn.e3mall.common.jedis;
      2 
      3 import java.util.List;
      4 
      5 import redis.clients.jedis.Jedis;
      6 import redis.clients.jedis.JedisPool;
      7 
      8 public class JedisClientPool implements JedisClient {
      9     
     10     private JedisPool jedisPool;
     11 
     12     public JedisPool getJedisPool() {
     13         return jedisPool;
     14     }
     15 
     16     public void setJedisPool(JedisPool jedisPool) {
     17         this.jedisPool = jedisPool;
     18     }
     19 
     20     @Override
     21     public String set(String key, String value) {
     22         Jedis jedis = jedisPool.getResource();
     23         String result = jedis.set(key, value);
     24         jedis.close();
     25         return result;
     26     }
     27 
     28     @Override
     29     public String get(String key) {
     30         Jedis jedis = jedisPool.getResource();
     31         String result = jedis.get(key);
     32         jedis.close();
     33         return result;
     34     }
     35 
     36     @Override
     37     public Boolean exists(String key) {
     38         Jedis jedis = jedisPool.getResource();
     39         Boolean result = jedis.exists(key);
     40         jedis.close();
     41         return result;
     42     }
     43 
     44     @Override
     45     public Long expire(String key, int seconds) {
     46         Jedis jedis = jedisPool.getResource();
     47         Long result = jedis.expire(key, seconds);
     48         jedis.close();
     49         return result;
     50     }
     51 
     52     @Override
     53     public Long ttl(String key) {
     54         Jedis jedis = jedisPool.getResource();
     55         Long result = jedis.ttl(key);
     56         jedis.close();
     57         return result;
     58     }
     59 
     60     @Override
     61     public Long incr(String key) {
     62         Jedis jedis = jedisPool.getResource();
     63         Long result = jedis.incr(key);
     64         jedis.close();
     65         return result;
     66     }
     67 
     68     @Override
     69     public Long hset(String key, String field, String value) {
     70         Jedis jedis = jedisPool.getResource();
     71         Long result = jedis.hset(key, field, value);
     72         jedis.close();
     73         return result;
     74     }
     75 
     76     @Override
     77     public String hget(String key, String field) {
     78         Jedis jedis = jedisPool.getResource();
     79         String result = jedis.hget(key, field);
     80         jedis.close();
     81         return result;
     82     }
     83 
     84     @Override
     85     public Long hdel(String key, String... field) {
     86         Jedis jedis = jedisPool.getResource();
     87         Long result = jedis.hdel(key, field);
     88         jedis.close();
     89         return result;
     90     }
     91 
     92     @Override
     93     public Boolean hexists(String key, String field) {
     94         Jedis jedis = jedisPool.getResource();
     95         Boolean result = jedis.hexists(key, field);
     96         jedis.close();
     97         return result;
     98     }
     99 
    100     @Override
    101     public List<String> hvals(String key) {
    102         Jedis jedis = jedisPool.getResource();
    103         List<String> result = jedis.hvals(key);
    104         jedis.close();
    105         return result;
    106     }
    107 
    108     @Override
    109     public Long del(String key) {
    110         Jedis jedis = jedisPool.getResource();
    111         Long result = jedis.del(key);
    112         jedis.close();
    113         return result;
    114     }
    115 
    116 }
    Jedis操作单机版的实现类
     1 package cn.e3mall.common.jedis;
     2 
     3 import java.util.List;
     4 
     5 import redis.clients.jedis.JedisCluster;
     6 
     7 public class JedisClientCluster implements JedisClient {
     8     
     9     private JedisCluster jedisCluster;
    10     
    11 
    12     public JedisCluster getJedisCluster() {
    13         return jedisCluster;
    14     }
    15 
    16     public void setJedisCluster(JedisCluster jedisCluster) {
    17         this.jedisCluster = jedisCluster;
    18     }
    19 
    20     @Override
    21     public String set(String key, String value) {
    22         return jedisCluster.set(key, value);
    23     }
    24 
    25     @Override
    26     public String get(String key) {
    27         return jedisCluster.get(key);
    28     }
    29 
    30     @Override
    31     public Boolean exists(String key) {
    32         return jedisCluster.exists(key);
    33     }
    34 
    35     @Override
    36     public Long expire(String key, int seconds) {
    37         return jedisCluster.expire(key, seconds);
    38     }
    39 
    40     @Override
    41     public Long ttl(String key) {
    42         return jedisCluster.ttl(key);
    43     }
    44 
    45     @Override
    46     public Long incr(String key) {
    47         return jedisCluster.incr(key);
    48     }
    49 
    50     @Override
    51     public Long hset(String key, String field, String value) {
    52         return jedisCluster.hset(key, field, value);
    53     }
    54 
    55     @Override
    56     public String hget(String key, String field) {
    57         return jedisCluster.hget(key, field);
    58     }
    59 
    60     @Override
    61     public Long hdel(String key, String... field) {
    62         return jedisCluster.hdel(key, field);
    63     }
    64 
    65     @Override
    66     public Boolean hexists(String key, String field) {
    67         return jedisCluster.hexists(key, field);
    68     }
    69 
    70     @Override
    71     public List<String> hvals(String key) {
    72         return jedisCluster.hvals(key);
    73     }
    74 
    75     @Override
    76     public Long del(String key) {
    77         return jedisCluster.del(key);
    78     }
    79 
    80 }
    集群版实现类

    application-redis.xml配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
    	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
    	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
    	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
    	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
    	
    	<!-- 连接redis单机版 -->
    	<bean id="jedisClientPool" class="cn.e3mall.common.jedis.JedisClientPool">
    		<property name="jedisPool" ref="jedisPool"></property>
    	</bean>
    	<bean id="jedisPool" class="redis.clients.jedis.JedisPool">
    		<constructor-arg name="host" value="127.0.0.1"/>
    		<constructor-arg name="port" value="6379"/>
    	</bean>
    	
    	<!-- 连接redis集群 -->
    	<bean id="jedisClientCluster" class="cn.e3mall.common.jedis.JedisClientCluster">
    		<property name="jedisCluster" ref="jedisCluster"/>
    	</bean>
    	<bean id="jedisCluster" class="redis.clients.jedis.JedisCluster">
    		<constructor-arg name="nodes">
    			<set>
    				<bean class="redis.clients.jedis.HostAndPort">
    					<constructor-arg name="host" value="127.0.0.1"/>
    					<constructor-arg name="port" value="7001"/>
    				</bean> 
    				<bean class="redis.clients.jedis.HostAndPort">
    					<constructor-arg name="host" value="127.0.0.1"/>
    					<constructor-arg name="port" value="7002"/>
    				</bean> 
    				<bean class="redis.clients.jedis.HostAndPort">
    					<constructor-arg name="host" value="127.0.0.1"/>
    					<constructor-arg name="port" value="7003"/>
    				</bean> 
    				<bean class="redis.clients.jedis.HostAndPort">
    					<constructor-arg name="host" value="127.0.0.1"/>
    					<constructor-arg name="port" value="7004"/>
    				</bean> 
    				<bean class="redis.clients.jedis.HostAndPort">
    					<constructor-arg name="host" value="127.0.0.1"/>
    					<constructor-arg name="port" value="7005"/>
    				</bean> 
    				<bean class="redis.clients.jedis.HostAndPort">
    					<constructor-arg name="host" value="127.0.0.1"/>
    					<constructor-arg name="port" value="7006"/>
    				</bean> 
    			</set>
    		</constructor-arg>
    	</bean>
    </beans>

    新增缓存后

    @Service
    @Transactional
    public class ContentServiceImpl implements ContentService {
    
        @Autowired
        private TbContentMapper contentMapper;
    
        @Autowired
        private JedisClient jedisClient;
    
    
        @Value("${CONTENT_LIST}")
        private String CONTENT_LIST;
    
        /**
         * 保存(大广告..)内容
         * @param content
         * @return
         */
        @Override
        public E3Result save(TbContent content) {
    
            // 1.封装参数
            content.setCreated(new Date());
            content.setCreated(new Date());
    
            // 2.插入
            contentMapper.insert(content);
    
            try {
                jedisClient.hdel(CONTENT_LIST,content.getCategoryId().toString());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
            // 3.返回
            return E3Result.ok();
        }
    
        /**
         * 根据分类id,取出各个分类的数据
         * @param i
         * @return
         */
        @Override
        public List<TbContent> findByCategoryId(Long i) {
    
            try{
                // 1)先从redis缓存中获取,需要的是字符串格式
                String json = jedisClient.hget(CONTENT_LIST, i + "");
                // 2)转成list
                if(StringUtils.isNotBlank(json)){
                    List<TbContent> list = JsonUtils.jsonToList(json, TbContent.class);
                    return list;
                }
            } catch (Exception ex){
                ex.printStackTrace();
            }
    
            // 1.设置查询条件
            TbContentExample example = new TbContentExample();
            TbContentExample.Criteria criteria = example.createCriteria();
            criteria.andCategoryIdEqualTo(i);
            // 2.执行查询并返回
            List<TbContent> list = contentMapper.selectByExampleWithBLOBs(example);
    
            try {
                // 1)将list转成字符串
                String json = JsonUtils.objectToJson(list);
                // 2)设置到redis中
                jedisClient.hset(CONTENT_LIST,i+"",json);
    
            }catch (Exception ex){
                ex.printStackTrace();
            }
    
            return list;
        }
    }
    
  • 相关阅读:
    最受欢迎的北大通选课导读·1[精品]
    社会保险,
    养老金的计算,
    毫秒 后的一个计算,
    返回格式 的数据结构再次改造,
    阶段状态池子,
    生活,-摘
    融合,
    tableview 也可以实现这个效果,
    字体大小 一致起来,
  • 原文地址:https://www.cnblogs.com/x54256/p/8645392.html
Copyright © 2020-2023  润新知