redis 的安装和简单使用

  • 一种nosql 单线程的数据库做缓存的简单使用
  • 对curd的操作,为了保证数据的一致性,除了查询,其它操作都要进行数据更新和删除
  • redis的协议:Redis服务器与客户端通过RESP(REdis Serialization Protocol)协议通信,了解了Redis协议的基本数据类型,就可以通过Socket与Redis Server进行通信,客户端和服务器发送的命令或数据一律以 \r\n (CRLF)结尾。
  • 缓存击穿 指查询一个一定不存在的数据要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞;解决方法如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短
  • 缓存雪崩 缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩;解决方案在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,降低几率;或则加锁,队列
  • 关于缓存击穿和雪崩参考

安装服务

  • http://www.redis.cn/ 下载最新redis4.01
  • #tar -zxvf redis... --解压
  • #mv file filepath --移动到你想安装的目录
  • #cd /redis
  • #make MALLOC=libc --管理内存碎片
  • #make && make install --编译并安装
  • #cd src && redies-server 如图
    redis 的安装和简单使用_第1张图片
    image.png

配置

  • #vi /home/redis/src/redis.conf --编写配置文件,写入已下配置,指定端口-父进程pid-守护进程
    image.png
  • #通过src/redis-server redis.conf 启动 通过#redis-cli shutdown 来停止服务
  • 会有两个端口打开未发现有什么错误,可以禁用ip6,
    image.png
  • #firewall-cmd --zone=public --add-port=6379/tcp --perment
  • #vi /usr/lib/systemd/system/redis.service --编写服务单元交与systemd 管理
    redis 的安装和简单使用_第2张图片
    image.png

rdb和aof 两种持久化方案详情1详情2

  • rdb 是基于快照的,通过save seconds frequency,进行周期性的备份默认开启,当服务器出现故障可能会丢失最后一次的数据。数据恢复速度快适合数据的备份。
    redis 的安装和简单使用_第3张图片
    image.png
  • aof 是基于日志记录的,保持了高一致性。数据比较全面文件比较大恢复稍慢。默认是关闭的通过appendonly yes开启。


    redis 的安装和简单使用_第4张图片
    image.png

简单的使用

  1. 使用java操作jedis客户端
  • 编写jedisManager
导入依赖

    redis.clients
    jedis
    2.9.0
  
redis的连接初始化类

public class JedisManager {
    private static String host = "192.168.1.200";
    private static int port = 6379;
    private JedisPoolConfig jpc;
    private static JedisPool jedisPool;
    private static int timeOut;

    /**
     * 初始化连接池
    **/
    static {
        if (timeOut == 0){
            timeOut = Protocol.DEFAULT_TIMEOUT;
        }
        jedisPool = new JedisPool(host,port);
    }

    /**
     * 从连接池中获取连接
    **/
    public static Jedis getJedis(){
        if (jedisPool != null){
            return jedisPool.getResource();
        }else throw new NullPointerException("jedisPool is null");
    }

    /**
     * 把连接返回给jedispool
    **/
    public static void  returnResource(Jedis jedis) {
        if (jedis != null){
            jedisPool.close();
        }
    }

    /**
     * 关闭连接池
    **/
    public void shutDown(){
        if (jedisPool != null){
            jedisPool.destroy();
        }
    }
}
String类型的测试

public class JedisDao {
    //存储字符串
    public void cacheString(){
        Jedis jedis = JedisManager.getJedis();
        System.out.println(jedis);
        jedis.set("name","hahaha");
        System.out.println(jedis.get("name"));
        //拼接
        jedis.append("name","is 爸爸");
        System.out.println(jedis.get("name"));
        JedisManager.returnResource(jedis);
    }

}
测试结果

redis.clients.jedis.Jedis@7bb11784
hahaha
hahahais 爸爸
Process finished with exit code 0
  1. 整合spring 分别在service层缓存,利用spirng aop 对目标方法进行缓存
导入依赖


      redis.clients
      jedis
       2.9.0
  
  
      org.springframework.data
       spring-data-redis
        1.7.2.RELEASE
 

    aspectj
    aspectjweaver
     1.5.4
  
redis.properties

redis.host=192.168.1.200
redis.port=6379
redis.password=
#最大空闲数
redis.maxIdel=300
#连接池连接数
redis.maxActive=600
#最大等待时间
redis.maxWait=1000
#实例均用
redis.testOnBorrow=true
reids-cfg.xml




    
     
        
        
        
            
                classpath:redis.properties
            
        
    
    
    
        
        
        
        

    

    
    
        
        
        
        
       

    

    
    
        
        
        
            
        
        
            
        
        
        
    


放入spring的主配置文件

    
    
  • 测试在service层进行缓存
 需要的工具类

@Component
public class RedisCacheUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 删除对应的value
    **/
    public void remove(final String... args){
        for (String key:args){
           remove(key);
        }
    }
    public boolean remove(String key){
        boolean flag = false;
        try {
            if (exists(key)){
                redisTemplate.delete(key);
                flag = true;
            }
        }catch (Exception e) {
            System.out.println(e.toString());
        }
        return flag;
    }

    public boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }


    /**
     * 删除keys
    **/
    public void removePattern(final String pattern){
        Set keys = redisTemplate.keys(pattern);
        if (keys.size()>0){
            redisTemplate.delete(keys);
        }
    }

    /**
     * 根据key读取缓存
    **/
    public Object get(final String key){
         return redisTemplate.opsForValue().get(key);
    }
    
    /**
     * 写入缓存
    **/
    public boolean set(final String key, Object value){
        try {
            redisTemplate.opsForValue().set(key,value);
            return true;
        }catch (Exception e){
            System.out.println(e.toString());
            return false;
        }
    }

    public boolean set(final String key, Object value, Long time){ //设置过期时间
        try {
            redisTemplate.opsForValue().set(key, value);
            redisTemplate.expire(key,time, TimeUnit.SECONDS);
            return true;
        }catch (Exception e){
            return false;
        }
    }
}

缓存的容器

/**
 * Created by: jun on 2018/1/7.
 * description: 创建redis的储存器接口
 */
public interface RedisCacheStorage {
    //key,value 普通类型
    boolean set(k key, v value);    //永久缓存
    boolean set(k key, v value, Long time); //time内缓存
    boolean remove(k key);  //删除
    v get(k key);   //获取
 }

// 实现的接口
@Component
public class RedisCacheStorageImpl implements RedisCacheStorage {

    @Autowired
    private RedisCacheUtil redisCacheUtil;

    @Override
    public boolean set(String key, v value) {
        return redisCacheUtil.set(key,value);
    }

    @Override
    public boolean set(String key, v value, Long time) {
        return redisCacheUtil.set(key,value,time);
    }

    @Override
    public boolean remove(String key) {
        return redisCacheUtil.remove(key);
    }

    @Override
    public v get(String key) {
        return (v) redisCacheUtil.get(key);
    }
}
实体类,一定要序列化,spirng 才能进行装配

public class User implements Serializable {

    private Integer id;
    private String name;
    private String pwd;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}
开始缓存

@Service
public class UserServiceImpl implements UserService {

    private static final String cacheKey = "userEntity"; //缓存的key
    private static final Long time = 10000l;

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RedisCacheStorage cacheStorage;

    @Override
    public List select() {
        //先查找缓存
        List userList;
        userList = (List) cacheStorage.get(cacheKey);
        if (userList != null) {
            System.out.println("读取了缓存");
            return userList;
        } else {
            //开始查找数据库,放入缓存
            userList = userMapper.selectAll();
            cacheStorage.set(cacheKey, userList);
            System.out.println("已添加缓存");
            return userList;
        }
    }

测试结果


image.png
  • 测试基于aop配置文件目标方法的缓存
实现MethodInterceptor接口的切面,在redis.properties中写入需要缓存的方法如果与aop拦截的方法对应则进行缓存

/**
 * Created by: jun on 2018/1/3.
 * description: 实现spring MethodInterceptor接口,使用aop对方法级的进行缓存。
 *              根据配置文件给不同的方法加入判断是否缓存数据,第一次从缓存中读取,并将结果进行缓存
 */
public class MethodCacheInterceptor implements MethodInterceptor {

    @Autowired
    private RedisCacheUtil redisCacheUtil;
    private List cacheClassList;    //缓存的serice类
    private List cacheMethodList;    //缓存的方法
    private Long timeOut = 1000l;   //过期时间
    private String resourcesName = "redis.properties";  //缓存的配置文件
    private String fileClassValue = "cacheClass";    //配置文件设置缓存的类字段
    private String fileMethodValue = "cacheMethod";     //配置文件中缓存的方法字段


    /**
     * 初始化读取需要缓存的类和方法
     * 在reids.properties中添加缓存的方法和类
     *
    **/
    public MethodCacheInterceptor() throws IOException {
        // 在 resources 下读取配置文件
        InputStream in = ConfProLoader.getClassPathFile(resourcesName);
        Properties p = new Properties();
        p.load(in);
        //分割,获取每个类和方法
        String[] cacheClass = p.getProperty(fileClassValue).split(",");
        String[] cacheMethod = p.getProperty(fileMethodValue).split(",");
        //将方法和类存入list
        cacheClassList = new ArrayList(cacheClass.length);
        cacheMethodList = new ArrayList(cacheMethod.length);
        int maxLength = cacheClass.length > cacheMethod.length ? cacheClass.length
                : cacheMethod.length;
        for (int i=0; i0) sb.append("_").append(arguments[i]);
        }
        return sb.toString();
    }
}
在reids的资源文件中写入需要缓存的类和方法。如果拦截的方法和配置文件中对应,则对该方法进行缓存

host=192.168.1.200
port=6379
password=

#连接池连接数
maxTotal=400
#最大空闲数
maxIdel=300
#最大等待时间
maxWait=1000
#实例均用
testOnBorrow=true


#需要缓存的类
cacheClass=comm.tianzhuan.web.service.impl.UserServiceImpl,test1
#要缓存的方法
cacheMethod=selectt,hahaha

#设置缓存失效时间
test=60
test1=60
defaultCacheExpireTime=3600

spirng中配置aop

 
    
    
        
        
        
        
    

测试的结果

@Test
    public void test(){
        List userList = userService.select();
        System.out.println(userList);
    }
image.png

你可能感兴趣的:(redis 的安装和简单使用)