Redis环境搭建
环境
- MacOS (本篇博客介绍)
- Windows (坑比较少,网上教程也比较多,比如这篇)
Redis配置步骤
 有两种方案可以配置Redis,【1】官网下载安装包方式【2】通过homebrew安装方式
安装包方式
- 下载安装包 - 去Redis官网下载Stable 稳定版  
- 安装 - 这里通过命令行安装,在解压后的目录下 - redis-6.2.2:
- 编译测试: - sudo make test
- 编译安装: - sudo make install- 安装完后可以看见目录如下: 
 
- Redis配置 - 注意这里坑比较多!!!先找到 - redis.conf文件,这是redis的配置文件,我们一般需要配置的是服务器的登陆密码。可以打开文件后搜索- requirepass修改后面的的密码即可,注意还要去掉前面的- #。
 
 还可以继续配置aof或者rdb的持久方式:
- 开启RDB - 将包含save的那几行的 - #去掉即可 
- 开启AOF - 将apeendonly的值改为yes即可  
- 启动Redis服务 - 这里是个大坑!!!注意到上一步我们设置了conf文件,如果想要配置生效,启动的时候需要加上conf文件。直接打开终端,将conf和 - redis-server文件拖入,后者先cd进入上面的redis解压目录。 
 
 然后回车即可看见服务正常启动,看到下面的界面就可以了。
 
 这里如果觉得每次麻烦,可以封装成一个执行文件:
- vim redis - 新建名为redis的文件,写入 - /.../redis-6.2.2/src/redis-server /.../redis-6.2.2/redis.conf
- 给文件添加执行全县 - chmod +x redis
- 启动服务 - ./redis
- 注意 - 上述带有conf文件的启动方式,即使你通过 - control+c关掉服务后,redis服务会依然在后台启动,若是修改配置后重启,可以在mac的- 活动监视器搜索- redis关掉服务,再通过步骤4启动服务。
 
homebrew方式
Springboot整合Redis
 配置好Redis是开发的第一步,如何使用才是关键,这里列出我平时通过Springboot使用Redis时的部分代码。我一般都是把Redis放在service层,供其他业务service调用。
- pom依赖 - <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
- Redis的yaml配置 
spring:
#redis
   redis:
      host: localhost
      password: 123456
      port: 6379
      pool:
         max-idle: 100
         min-idle: 1
         max-active: 1000
         max-wait: -1- RedisService
列出的是Redis五种数据类型的crud,方法的传入参数可以根据自己的业务逻辑相应修改。
package com.qian.service;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
@Component
public class RedisService {
	@Autowired
	private RedisTemplate<Object, Object> redisTemplate;
	/*
	 * 字符串类型操作
	 */
	/**
	 * redisTemplate操作普通字符串(存值)
	 * 
	 * @param key
	 * @param value
	 */
	public void redisSetString(String key, String value) {
		redisTemplate.opsForValue().set(key, value);
	}
	/**
	 * redisTemplate操作普通字符串 (取值)
	 * 
	 * @param key
	 */
	public Object redisGetString(String key) {
		return redisTemplate.opsForValue().get(key);
	}
	
	/*
	 * 列表类型操作
	 */
	/**
     * 将一个list集合存放到redis当中
     * 
     * @param key
     */
    public void redisSetList(String key, List<Object> list) {
//        List<Integer> list = Arrays.asList(9, 2, 3, 4);
        for (Object obj : list) {
            // 从当前的数据 向右添加 
             redisTemplate.opsForList().rightPush(key, obj);
            // 从当前的数据 向左添加 
//            redisTemplate.opsForList().leftPush(key, obj);
        }
    }
    
    /**
     * 获取list(获取所有的数据)
     * 
     * @param key
     * @return
     */
    public Object getList(String key) {
        return redisTemplate.opsForList().range(key, 0, getListSize(key));
    }
    
    /**
     * 获取list指定key的长度
     * 
     * @param key
     * @return
     */
    public Long getListSize(String key) {
        return redisTemplate.opsForList().size(key);
    }
    
    
	/*
	 * 哈希类型操作
	 */
    /**
     * 将map存放到reids
     *
     * @param key
     */
    public void setHash(String key) {
        Map<String, String> hashMap = new HashMap();
        //使用RedisTemplate  有些情况会乱码
        hashMap.put("redis", "redis");
        hashMap.put("mysql", "mysql");
        for (Entry<String, String> keyValue : hashMap.entrySet()) {
            redisTemplate.opsForHash().put(key, keyValue.getKey(), keyValue.getValue());
        }
    }
    
    /**
     * 获取指定key1的值
     * 
     * @param key
     * @param key1
     * @return
     */
    public Object getHash(String key, String key1) {
        // 检测 是否 存在该键
        boolean isKey = redisTemplate.opsForHash().hasKey(key, key1);
        return redisTemplate.opsForHash().get(key, key1);
    }
    
    /**
     * 获取指定key的所有值
     * 
     * @param key
     * 
     * @return
     */
    public Object getHash(String key) {
        return redisTemplate.opsForHash().entries(key);
    }
    
    /**
     * 根据具体key移除具体的值
     * 
     * @param key
     * 
     * @return
     */
    public void removeKey(String key, String key1) {
        redisTemplate.opsForHash().delete(key, key1);
    }
    
    /**
     * 移除key值 则key里面的所有值都被移除
     * 
     * @param key
     * 
     * @return
     */
    public void removeStringKey(String key) {
        redisTemplate.delete(key);
    }
    
    
	/*
	 * 集合类型操作
	 */
    /**
     * set存入redis中
     * 
     * @param key
     */
    public void setSet(String key) {
        Set<Object> set = new HashSet();
        set.add("setKey");
        set.add("tesetKey");
        for (Object object : set) {
            redisTemplate.opsForSet().add(key, object);
        }
    }
    
    /**
     * 从redis中取出set
     * 
     * @param key
     * @return
     */
    public Object getSet(String key) {
        return redisTemplate.opsForSet().members(key);
    }
    
    
	/*
	 * 有序集合类型操作
	 */
    /**
     * sortset存入redis中
     * 
     * @param key
     */
    public void setZSet(String key) {
        Set<Object> set = new HashSet();
        set.add("setKey");
        set.add("tesetKey");
        int i = 0;
        for (Object object : set) {
            i++;
            redisTemplate.opsForZSet().add(key, object, i);
        }
    }
    
    /**
     * 从redis中取出sortset
     * 
     * @param key
     * @return
     */
    public Object getZSet(String key) {
        Long size = redisTemplate.opsForZSet().size(key);
        return redisTemplate.opsForZSet().rangeByScore(key, 0, size);
    }
    
    
    /*
     * RedisTemplate操作5种基本类型数据,有一些共同的API 
     */
    /**
     * 
     * 指定缓存失效时间
     * 
     * @param key
     *            键
     * 
     * @param time
     *            时间(秒)
     * 
     * @return
     * 
     */
    public boolean expire(String key, long time) {
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    
    /**
     * 
     * 判断key是否存在
     * 
     * @param key
     *            键
     * 
     * @return true 存在 false不存在
     * 
     */
    public boolean checkKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    
}
关于可视化工具的key/value乱码问题
我使用redis官方提供的Redisinsight,发现插入key后有乱码的问题。可以使用配置类设置序列化
@Configuration
public class RedisConfig {
	@Autowired
    private RedisTemplate redisTemplate;
    @Bean
    public RedisTemplate redisTemplateInit() {
        //设置序列化Key的实例化对象
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        //设置序列化Value的实例化对象
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
        return redisTemplate;
    }
}如果是使用的Fastjson对对象进行序列化,也可以自定义序列化类
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import com.alibaba.fastjson.parser.ParserConfig;
import org.springframework.util.Assert;
import java.nio.charset.Charset;
/**
 * Redis使用FastJson序列化
 * 
 * @author sg
 */
public class FastJsonRedisSerializer<T> implements RedisSerializer<T>
{
    public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
    private Class<T> clazz;
    static
    {
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    }
    public FastJsonRedisSerializer(Class<T> clazz)
    {
        super();
        this.clazz = clazz;
    }
    @Override
    public byte[] serialize(T t) throws SerializationException
    {
        if (t == null)
        {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }
    @Override
    public T deserialize(byte[] bytes) throws SerializationException
    {
        if (bytes == null || bytes.length <= 0)
        {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        return JSON.parseObject(str, clazz);
    }
    protected JavaType getJavaType(Class<?> clazz)
    {
        return TypeFactory.defaultInstance().constructType(clazz);
    }
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
public class RedisConfig {
    @Bean
    @SuppressWarnings(value = { "unchecked", "rawtypes" })
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
    {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        FastJsonRedisSerializer serializer = new FastJsonRedisSerializer(Object.class);
        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(serializer);
        // Hash的key也采用StringRedisSerializer的序列化方式
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        return template;
    }
} 
                     
                     
                        
                        