本人微信公众号"aeolian"~

Redis-CentOS7安装

安装

Redis是c语言开发的。

安装redis需要c语言的编译环境。如果没有gcc需要在线安装。yum install gcc-c++

安装步骤:

第一步:redis的源码包上传到linux系统。

第二步:解压缩redis。

第三步:编译。进入redis源码目录。make

《Redis-CentOS7安装》

第四步:安装。make install PREFIX=/usr/local/redis

PREFIX参数指定redis的安装目录。一般软件安装到/usr目录下

启动

前端启动:在redis的安装目录下直接启动redis-server

[root@localhost bin]# ./redis-server

后台启动:

把解压目录中的/root/redis-3.0.0/redis.conf复制到安装目录中/usr/local/redis/bin目录下

[root@localhost redis-3.0.0]# cp redis.conf /usr/local/redis/bin/

修改配置文件:

[root@localhost bin]# ./redis-server redis.conf

daemon yes    #守护进程改为是

查看redis进程:

[root@localhost bin]# ps aux|grep redis

root      5190  0.1  0.3  33936  1712 ?        Ssl  18:23   0:00 ./redis-server *:6379   

root      5196  0.0  0.1   4356   728 pts/0    S+   18:24   0:00 grep redis

关闭

[root@localhost bin]# kill 5190     #正常关闭

[root@localhost bin]# kill -9 5190     #强制关闭

[root@localhost bin]# ./redis-cli shutdown

连接

首先redis.conf文件中设置指定的ip和端口,更改后服务要重启

《Redis-CentOS7安装》

《Redis-CentOS7安装》

 

redis-cli -h 主机 -p 端口

[root@localhost bin]# ./redis-cli -h 192.168.25.3 -p 6379

《Redis-CentOS7安装》

常用命令

String:key-value(做缓存)

Redis中所有的数据都是字符串。命令不区分大小写,key是区分大小写的。Redis是单线程的。Redis中不适合保存内容大的数据。

get、set、incr:加一(生成id)、Decr:减一

设置键值对: set key value

获取指定键的值: get key

查看所有key:  keys *

删除键:del key

指定key的value加一: incr key

指定key的value减一: decr key

Hash :key-fields-values(做缓存)

相当于一个key对于一个map,map中还有key-value。使用hash对key进行归类。

Hset:向hash中添加内容

Hget:从hash中取内容

 

设置key的fields和values: hset key field value

获取指定key的field的值: hget key field

获取指定key的所有filed字段: hkeys key

获取指定key的所有值: hvals key

删除指定key的指定field字段: hdel key field

获取key的所有fiel和value信息: hgetall key

List:有顺序可重复

从左边添加:lpush key value [value..]   

从右边添加:rpush key value [value..]

获取所有list元素: lrange key start end

从左边取出(取出list集合中就不存在了):lpop key

从右边取出(取出list集合中依然不存在): rpop key

Set:元素无顺序,不能重复

在集合中添加元素(自动过滤重复元素): sadd key value[value..]

移除集合中的元素: srem key value[value..]

查看Set中的值:smembers key

第一个set和第二个set做比较: sdiff key1 key2 

交集: sinter key1 key2 

并集: sunion key1 key2

《Redis-CentOS7安装》

SortedSet(zset):有顺序,不能重复(消耗性能最高,能用list替代就用list)

按顺序给Set添加元素: zadd zset1 2 a 5 b 1 c 6 d

查看指定key中的所有元素: zrange zset1 0 -1

移除指定key中的指定元素: zrem zset1 a

查询的排序反转: zrange zset1 0 -1

连同排序号一起查出来: zrange zset1 0 -1 withscores

设置key的过期时间

expire key second:设置key的过期时间,一旦过期就清除

ttl key:查看key的有效期

persist key:清除key的过期时间。Key持久化。

持久化方案

Redis的所有数据都是保存到内存中的。

Rdb:快照形式,定期把内存中当前时刻的数据保存到磁盘。Redis默认支持的持久化方案。

《Redis-CentOS7安装》

aof形式:append only file。把所有对redis数据库操作的命令,增删改操作的命令。保存到文件中。数据库恢复时把所有的命令执行一遍即可。

《Redis-CentOS7安装》

集群

当redis中的数据是存放在内存中的。当内存存满时会存放在虚拟内存中(虚拟内存效率很低),为了解决这个问题要使用集群,redis每个节点存放的数据是不一样的。

 

架构细节:

(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集群中至少应该有三个节点。要保证集群的高可用,需要每个节点有一个备份机。

Redis集群至少需要6台服务器。

搭建伪分布式。可以使用一台虚拟机运行6个redis实例。需要修改redis的端口号7001-7006

集群搭建环境

1、使用ruby脚本搭建集群。需要ruby的运行环境。

安装ruby

yum install ruby

yum install rubygems

2、将redis-3.0.0.gem包上传到服务器,安装ruby脚本运行使用的包。

[root@localhost ~]# gem install redis-3.0.0.gem

Successfully installed redis-3.0.0

1 gem installed

Installing ri documentation for redis-3.0.0…

Installing RDoc documentation for redis-3.0.0…

3、从解压包中src下的redis-trib.rb复制到集群目录下

[root@localhost ~]# cd redis-3.0.0/src

[root@localhost src]# ll *.rb

-rwxrwxr-x. 1 root root 48141 Apr  1  2015 redis-trib.rb

[root@localhost src]# cp redis-trib.rb ../../java/redis-cluster/

搭建步骤

需要6台redis服务器。搭建伪分布式。

需要6个redis实例。

需要运行在不同的端口7001-7006

第一步:创建6个redis实例,每个实例运行在不同的端口。需要修改redis.conf配置文件。配置文件中还需要把cluster-enabled yes前的注释去掉。

《Redis-CentOS7安装》

第二步:启动每个redis实例。

启动redis-cluster文件夹下的六个redis
[root@localhost redis-cluster]# vim start-cluster.sh
cd redis0
./redis-server redis.conf
cd ..
cd redis1
./redis-server redis.conf
cd ..
cd redis2
./redis-server redis.conf
cd ..
cd redis3
./redis-server redis.conf
cd ..
cd redis4
./redis-server redis.conf
cd ..
cd redis5
./redis-server redis.conf
cd ..

[root@localhost redis-cluster]# chmod u+x start-cluster.sh 


创建关闭集群的脚本:
[root@localhost redis-cluster]# vi shutdow-all.sh
redis0/redis-cli -p 7000 shutdown
redis1/redis-cli -p 7001 shutdown
redis2/redis-cli -p 7002 shutdown
redis3/redis-cli -p 7003 shutdown
redis4/redis-cli -p 7004 shutdown
redis5/redis-cli -p 7005 shutdown

[root@localhost redis-cluster]# chmod u+x shutdow-all.sh 

第三步:使用ruby脚本搭建集群。

./redis-trib.rb create --replicas 1 192.168.25.3:7000 192.168.25.3:7001 192.168.25.3:7002 192.168.25.3:7003 192.168.25.3:7004 192.168.25.3:7005

Jedis

需要把jedis依赖的jar包添加到工程中。Maven工程中需要把jedis的坐标添加到依赖。

连接单机版

第一步:创建一个Jedis对象。需要指定服务端的ip及端口。

第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。

第三步:打印结果。

第四步:关闭Jedis。

    @Test
    public void testJedis() throws Exception {
        // 第一步:创建一个Jedis对象。需要指定服务端的ip及端口。
        Jedis jedis = new Jedis("192.168.25.3", 6379);
        // 第二步:使用Jedis对象操作数据库,每个redis命令对应一个方法。
        String result = jedis.get("hello");
        // 第三步:打印结果。
        System.out.println(result);
        // 第四步:关闭Jedis
        jedis.close();
    }
 

连接单机版使用连接池

第一步:创建一个JedisPool对象。需要指定服务端的ip及端口。

第二步:从JedisPool中获得Jedis对象。

第三步:使用Jedis操作redis服务器。

第四步:操作完毕后关闭jedis对象,连接池回收资源。

第五步:关闭JedisPool对象。

    @Test
    public void testJedisPool() throws Exception {
        // 第一步:创建一个JedisPool对象。需要指定服务端的ip及端口。
        JedisPool jedisPool = new JedisPool("192.168.25.153", 6379);
        // 第二步:从JedisPool中获得Jedis对象。
        Jedis jedis = jedisPool.getResource();
        // 第三步:使用Jedis操作redis服务器。
        jedis.set("jedis", "test");
        String result = jedis.get("jedis");
        System.out.println(result);
        // 第四步:操作完毕后关闭jedis对象,连接池回收资源。
        jedis.close();
        // 第五步:关闭JedisPool对象。
        jedisPool.close();
    }

连接集群

第一步:使用JedisCluster对象。需要一个Set参数。Redis节点的列表。

第二步:直接使用JedisCluster对象操作redis。在系统中单例存在。

第三步:打印结果

第四步:系统关闭前,关闭JedisCluster对象。

    @Test
    public void testJedisCluster() throws Exception {
        // 第一步:使用JedisCluster对象。需要一个Set参数。Redis节点的列表。
        Set nodes = new HashSet<>();
        nodes.add(new HostAndPort("192.168.25.153", 7001));
        nodes.add(new HostAndPort("192.168.25.153", 7002));
        nodes.add(new HostAndPort("192.168.25.153", 7003));
        nodes.add(new HostAndPort("192.168.25.153", 7004));
        nodes.add(new HostAndPort("192.168.25.153", 7005));
        nodes.add(new HostAndPort("192.168.25.153", 7006));
        JedisCluster jedisCluster = new JedisCluster(nodes);
        // 第二步:直接使用JedisCluster对象操作redis。在系统中单例存在。
        jedisCluster.set("hello", "100");
        String result = jedisCluster.get("hello");
        // 第三步:打印结果
        System.out.println(result);
        // 第四步:系统关闭前,关闭JedisCluster对象。
        jedisCluster.close();
    }

向业务逻辑中添加缓存

接口封装

常用的操作redis的方法提取出一个接口,分别对应单机版和集群版创建两个实现类。

/*接口定义*/
public interface JedisClient {
    String set(String key, String value);
    String get(String key);
    Boolean exists(String key);
    Long expire(String key, int seconds);
    Long ttl(String key);
    Long incr(String key);
    Long hset(String key, String field, String value);
    String hget(String key, String field);
    Long hdel(String key, String... field);
}
/*单机版实现类*/
public class JedisClientPool implements JedisClient {
    @Autowired
    private JedisPool jedisPool;

    @Override
    public String set(String key, String value) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.set(key, value);
        jedis.close();
        return result;
    }

    @Override
    public String get(String key) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.get(key);
        jedis.close();
        return result;
    }

    @Override
    public Boolean exists(String key) {
        Jedis jedis = jedisPool.getResource();
        Boolean result = jedis.exists(key);
        jedis.close();
        return result;
    }

    @Override
    public Long expire(String key, int seconds) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.expire(key, seconds);
        jedis.close();
        return result;
    }

    @Override
    public Long ttl(String key) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.ttl(key);
        jedis.close();
        return result;
    }

    @Override
    public Long incr(String key) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.incr(key);
        jedis.close();
        return result;
    }

    @Override
    public Long hset(String key, String field, String value) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.hset(key, field, value);
        jedis.close();
        return result;
    }

    @Override
    public String hget(String key, String field) {
        Jedis jedis = jedisPool.getResource();
        String result = jedis.hget(key, field);
        jedis.close();
        return result;
    }

    @Override
    public Long hdel(String key, String... field) {
        Jedis jedis = jedisPool.getResource();
        Long result = jedis.hdel(key, field);
        jedis.close();
        return result;
    }
}


    class="redis.clients.jedis.JedisPool">
        
        
    
    class="com.e3mall.common.jedis.JedisClientPool">
        
    


/*集群版实现类*/
package cn.e3mall.jedis;

import org.springframework.beans.factory.annotation.Autowired;

import redis.clients.jedis.JedisCluster;

public class JedisClientCluster implements JedisClient {
    
    @Autowired
    private JedisCluster jedisCluster;

    @Override
    public String set(String key, String value) {
        return jedisCluster.set(key, value);
    }

    @Override
    public String get(String key) {
        return jedisCluster.get(key);
    }

    @Override
    public Boolean exists(String key) {
        return jedisCluster.exists(key);
    }

    @Override
    public Long expire(String key, int seconds) {
        return jedisCluster.expire(key, seconds);
    }

    @Override
    public Long ttl(String key) {
        return jedisCluster.ttl(key);
    }

    @Override
    public Long incr(String key) {
        return jedisCluster.incr(key);
    }

    @Override
    public Long hset(String key, String field, String value) {
        return jedisCluster.hset(key, field, value);
    }

    @Override
    public String hget(String key, String field) {
        return jedisCluster.hget(key, field);
    }

    @Override
    public Long hdel(String key, String... field) {
        return jedisCluster.hdel(key, field);
    }
}


    class="redis.clients.jedis.JedisCluster">
        
            
                class="redis.clients.jedis.HostAndPort">
                    
                    
                
                class="redis.clients.jedis.HostAndPort">
                    
                    
                
                class="redis.clients.jedis.HostAndPort">
                    
                    
                
                class="redis.clients.jedis.HostAndPort">
                    
                    
                
                class="redis.clients.jedis.HostAndPort">
                    
                    
                
                class="redis.clients.jedis.HostAndPort">
                    
                    
                
            
        
    
    class="com.e3mall.common.jedis.JedisClientCluster">
        
    

注意:单机版和集群版不能共存,使用单机版时注释集群版的配置。使用集群版,把单机版注释。

封装代码测试

    @Test
    public void testJedisClient() throws Exception {
        //初始化Spring容器
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-redis.xml");
        //从容器中获得JedisClient对象
        JedisClient jedisClient = applicationContext.getBean(JedisClient.class);
        jedisClient.set("first", "100");
        String result = jedisClient.get("first");
        System.out.println(result);
    }

添加缓存

功能分析

查询内容列表时添加缓存。

1、查询数据库之前先查询缓存。

2、查询到结果,直接响应结果。

3、查询不到,缓存中没有需要查询数据库。

4、把查询结果添加到缓存中。

5、返回结果。

 

向redis中添加缓存:

Key:cid

Value:内容列表。需要把java对象转换成json。

 

使用hash对key进行归类。

HASH_KEY:HASH

            |–KEY:VALUE

            |–KEY:VALUE

            |–KEY:VALUE

            |–KEY:VALUE

注意:添加缓存不能影响正常业务逻辑。

String key = this.getClass().getName() +"."+ Thread.currentThread().getStackTrace()[1].getMethodName(); //包名.类名.方法名
String field = "sys_information_type:"+sys_information_type+",id:"+id;    //方法参数 
if (jedisClient.hget(key, field)!=null) { //判断redis中是否存在 System.out.println("从redis中取"); //向客户端输出 resp.reset(); resp.setContentType("text/plain; charset=UTF-8"); resp.setCharacterEncoding("utf-8"); resp.getOutputStream().write(jedisClient.hget(key, field).getBytes("utf-8")); resp.getOutputStream().flush(); return null; }
//将数据库中查找的数据转换为json格式存储到redis中 JSONObject jsonObject=new JSONObject(); 从数据库中查找数据... //将查询到的数据存储在redis中 jedisClient.hset(key, field, jsonObject.toString()); jedisClient.expire(key, 60); //经常更新的数据可以设置过期时间,单位秒
     返回数据...

缓存同步

对内容信息做增删改操作后只需要把对应缓存删除即可。不用把整个hash删掉,删掉hash指定的field即可。

jedisClient.expire(key, 0);    //将指定key设过期,string,hash都可以

——————————–20180725分割线——————–

spring+jackson环境

封装类RedisTool.java类

public class RedisTool {

    @Autowired
    JedisClient jedisClient;

    public JedisClient getJedisClient() {
        return jedisClient;
    }

    public void setJedisClient(JedisClient jedisClient) {
        this.jedisClient = jedisClient;
    }

    public RedisTool() {
    }

    /**
     * 查询是否存在
     * @Pa
     * @param paramString 参数拼接成的字符串
     * @return 存在返回json字符串,不存在返回none
     * @throws UnsupportedEncodingException
     */
    public String getReids(String key,String paramString){
        //String key = this.getClass().getName() +"."+ Thread.currentThread().getStackTrace()[1].getMethodName(); //包名.类名.方法名
        String field = paramString;    //方法参数
        if (jedisClient.hget(key, field)!=null) {    //判断redis中是否存在
            String result = jedisClient.hget(key, field);
            System.out.println("从redis中取"+result);
            //向客户端输出
            return result;
        }
        return "none";
    }


    /**
     * 向redis中添加
     * @param paramString 参数拼接成的字符串
     * @param jsonObject 结果- 缓存到redis中的字符串
     * @throws UnsupportedEncodingException
     */
    public void setReids(String key,String paramString,String jsonObject) throws UnsupportedEncodingException {
        String field = paramString;
        //String key = this.getClass().getName() +"."+ Thread.currentThread().getStackTrace()[1].getMethodName(); //包名.类名.方法名
        jedisClient.hset(key, field, jsonObject);
        jedisClient.expire(key, 60);     //经常更新的数据可以设置过期时间,单位秒
    }
}

Controller层

    @RequestMapping("/getAllBook")
    @ResponseBody
    public Page getAllBook(String pageNo,String pageSize,String cateCode_search,String money_search_start,String money_search_end,String time_search_start,String time_search_end,String remark_search,HttpServletRequest request,HttpServletResponse response) throws IOException {
       pageNo=pageNo==null?"1":pageNo;   //当前页码
        pageSize=pageSize==null?"5":pageSize;   //页面大小
        /*从redis中读取*/
        //key参数
        String redis_key = this.getClass().getName() +"."+ Thread.currentThread().getStackTrace()[1].getMethodName(); //包名.类名.方法名
        String userId = ((Users)request.getSession().getAttribute("user")).getId().toString();
        //field参数
        String paramString = "userId"+userId+"pageNo:"+pageNo+"pageSize"+pageSize+"cateCode_search"+cateCode_search+"money_search_start"+money_search_start+"money_search_end"+money_search_end+"time_search_start"+time_search_start+"time_search_end"+time_search_end+"remark_search"+remark_search;
        if(redisTool.getReids(redis_key,paramString)!="none"){  //读取
            Page page = null;
            try {
                page = new ObjectMapper().readValue(redisTool.getReids(redis_key,paramString),Page.class);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
            return page;
        }

        //
        //获取当前页数据
        List list = bookService.getAllBookByPage(userId,cateCode_search,money_search_start,money_search_end,time_search_start,time_search_end,remark_search,pageNo,pageSize);
        //获取总数据大小
        int totals = bookService.getAllBookCount(userId,cateCode_search,money_search_start,money_search_end,time_search_start,time_search_end,remark_search);
        //封装返回结果
        Page page = new Page();
        page.setTotal(totals+"");
        page.setRows(list);
        /*存入redis中*/
        String jsonResult =  new ObjectMapper().writeValueAsString(page);
        redisTool.setReids(redis_key,paramString,jsonResult);
        
        return page;
    }

applicationContext-redis.xml



       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">
    class="org.apache.commons.pool2.impl.GenericObjectPoolConfig" id="poolConfig">
    
    
    class="redis.clients.jedis.JedisPool">
        
        
        
        
        
    
    class="com.autumn.redis.JedisClientPool" id="jedisClientPool">
        
    
    class="com.autumn.redis.RedisTool">
        
    

web.xml

    
    
        contextConfigLocation
        classpath:spring/applicationContext-*.xml
    

 

点赞

Leave a Reply

Your email address will not be published. Required fields are marked *