Redis

2017-10-30  本文已影响82人  番薯IT

1. 设置密码


2. 登陆

2.1 linux

2.2 windows

redis-cli -h 127.0.0.1 -p 6379 123456


3. spring-data-redis

3.1 spring 和 redis 整合

spring的强大,我们都知道。springspring-data-redis就是spring提供的和redis整合的包装jar。

3.1.1 maven

目前最新的版本是1.7.2

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.7.2.RELEASE</version>
</dependency>

3.1.2 配置RestTemplate

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <property name="maxIdle" value="${redis.maxIdle}" />
    <property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
    <property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>

<bean id="jedisConnectionFactory"
    class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    <property name="usePool" value="true" />
    <property name="hostName" value="${redis.hostName}" />
    <property name="port" value="${redis.port}" />
    <property name="password" value="${redis.password}" />
    <property name="database" value="1" />
    <property name="poolConfig" ref="jedisPoolConfig" />
</bean>

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
    <property name="connectionFactory" ref="jedisConnectionFactory" />
</bean>

3.1.3 注入和使用RestTemplate

public class Example {

    // inject the actual template
    @Autowired
    private RedisTemplate<String, String> template;

    // inject the template as ListOperations
    // can also inject as Value, Set, ZSet, and HashOperations
    @Resource(name="redisTemplate")
    private ListOperations<String, String> listOps;

    public void addLink(String userId, URL url) {
        listOps.leftPush(userId, url.toExternalForm());
        // or use template directly
        redisTemplate.boundListOps(userId).leftPush(url.toExternalForm());
    }
}

3.2 数据类型

redis有五种数据结构,分别是:string,hash,list,set,zset。spring提供了这5种方式,下图是我从官方文档中截取的。提供了对应5中类型的包装类。这5个类都可以由RedisTemplate获取得到。

123.png

3.3 序列化

3.3.1 序列化配置

<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" >
    <property name="connectionFactory" ref="jedisConnectionFactory" />
    <!-- 默认 key 和 value 的序列化方式 -->
    <property name="defaultSerializer">
        <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />
    </property>
    <!-- 非 hash 的 key 的序列化方式 -->
    <property name="keySerializer" >
        <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
    </property>
    <!-- 非 hash 的 value 的序列化方式 -->
    <property name="valueSerializer">
        <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
    </property>
    <!-- hash 的 key 的序列化方式 -->
    <property name="hashKeySerializer">
        <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
    </property>
    <!-- hash 的 value 的序列化方式 -->
    <property name="hashValueSerializer">
        <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" />
    </property>
</bean>

如果redisTemplate中没有配置defaultSerializer,那么默认会使用JdkSerializationRedisSerializer,我们可以看下RedisTemplate中的afterPropertiesSet()方法下的部分源码:

if (defaultSerializer == null) {
defaultSerializer = new JdkSerializationRedisSerializer(
        classLoader != null ? classLoader : this.getClass().getClassLoader());
}

如果没有设置keySerializer和valueSerializer,那么默认的就是defaultSerializer。

3.3.2 序列化策略

StringRedisSerializer

序列化成String类型。当然这种方式是最高效的,redis设计就是这样的。但是这种策略是不能满足我们的。我们是有实体的,这种不好存储实体

JdkSerializationRedisSerializer

序列化成16进制字节序列。这种方式用的比较多吧,虽然是最消耗内存的,但是既然用缓存了,也就不在乎内存了吧!

OxmSerializer

序列化成xml。略过

Jackson2JsonRedisSerializer

序列化成json。这种方式比较笨重,每次都要指定对应的实体。执行效率比>较低。在后面我们会比较为什么执行效率低。

JacksonJsonRedisSerializer

此序列方式在spring-data-redis-1.7.2.RELEASE.jar中已经过时了。取而代之的是上面的方式。都是为了序列换成json的方式

3.3.3 序列化方式

3.3.3.1 前期定义

(1). 定义一个实体 StringDemo。自己添加getter和setter以及toString方法。实现Serializer方法,才能序列化。

public class StringDemo implements Serializable{
    private static final long serialVersionUID = -6209797447467016710L;
    private String id;
    private String name;
    private int age;
    private Date birth;
}

(2). 定义实现方式

@Service
public class RedisStringServiceImpl implements RedisStringService {
    
    @Resource
    private RedisTemplate<String, StringDemo> redisTemplate;
    
    private ValueOperations<String, StringDemo> valueOperation;
    
    @Resource(name = "redisTemplate")
    private ValueOperations<String, String> valueOps;
    
    @PostConstruct
    public void init(){
        valueOperation = redisTemplate.opsForValue();
    }
    
    /**
     * JDK序列化方式序列对象
     * applicationContent.xml中valueSeriazer 需要配置成 JdkSerializationRedisSerializer
     */
    @Override
    public void object2JDKSerializer(StringDemo demo){
        valueOperation.set("jdk2Object", demo);
    }
    
    /**
     * 从 REDIS 中获取对象
     * @return
     */
    @Override
    public StringDemo jdkSerializer2Object(){
        return valueOperation.get("jdk2Object");
    }
    
    
    /**
     * jackson的方式要指定 class。所以在配置总不好配置,所以就在程序中手动配置。
     * <p>
     * json的处理方式jackson是一种,还有的直接将实体转换成json,但是泛型的方式也要做相应的修改 <br>
     * 至于使用哪一种来序列化。就随便了。fastjson、gson等等
     */
    @Override
    public void Object2JacksonSerializer(StringDemo demo){
        Jackson2JsonRedisSerializer<StringDemo> jackson = new Jackson2JsonRedisSerializer<StringDemo>(StringDemo.class);
        redisTemplate.setValueSerializer(jackson);
        valueOperation.set("jackson2Object", demo);
    }
    
    @Override
    public StringDemo jacksonSerializer2Object(){
        Jackson2JsonRedisSerializer<StringDemo> jackson = new Jackson2JsonRedisSerializer<StringDemo>(StringDemo.class);
        redisTemplate.setValueSerializer(jackson);
        return valueOperation.get("jackson2Object");
    }
    
    /**
     * 使用fastjson的方式序列化
     * applicationContent.xml中valueSeriazer 需要配置成 StringRedisSerializer
     */
    @Override
    public void object2Fastjson(StringDemo demo){
        String demoStr = JSON.toJSONString(demo);
        valueOps.set("fastjson2Object", demoStr);
    }
    
    @Override
    public StringDemo fastjson2Object(){
        String demoStr = valueOps.get("fastjson2Object");
        return JSON.parseObject(demoStr, StringDemo.class);
    }
}

(3). 测试类

public class RedisStringServiceTest {
    private ApplicationContext ctx;
    private RedisStringService redisStringService;
    private long start;
    private long end;

    @Before
    public void init() {
        ctx = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        redisStringService = ctx.getBean(RedisStringServiceImpl.class);
        start = System.currentTimeMillis();
    } 
    
    @After
    public void after(){
        end = System.currentTimeMillis();
        System.out.println("cost time : " + (end - start) + "ms");
    }
    
    @Test
    public void testSerializer(){
        redisStringService.testSerializer();
    }
    
    @Test
    /**
     * \xAC\xED\x00\x05sr\x007com.roachfu.study.module.string.model.entity.StringDemo\xA9\xD2^\x1FX\x99\xDD\xFA\x02\x00\x04I\x00\x03ageL\x00\x05birtht\x00\x10Ljava/util/Date;L\x00\x02idt\x00\x12Ljava/lang/String;L\x00\x04nameq\x00~\x00\x02xp\x00\x00\x00\x19sr\x00\x0Ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\x08\x00\x00\x01W\x03\xBF\xD8\xB5xt\x00\x0510000t\x00\x05roach
     * <p>
     * 由上得出,以16进制保存的方式将实体的信息都保存了。可见占用的内存比较大。如果实体改变了包名,那么将不能反序列化
     * 结果耗时是:35ms左右
     */
    public void object2JDKSerializerTest(){
        StringDemo demo = new StringDemo();
        demo.setId("10000");
        demo.setAge(25);
        demo.setName("roach");
        demo.setBirth(new Date());
        
        redisStringService.object2JDKSerializer(demo);
    }
    
    /**
     * 平均耗时75ms左右
     */
    @Test
    public void jdkSerializer2ObjectTest(){
        StringDemo demo = redisStringService.jdkSerializer2Object();
        System.out.println(demo);
    }
    
    /**
     * 平均180ms左右
     */
    @Test
    public void Object2JacksonSerializerTest(){
        StringDemo demo = new StringDemo();
        demo.setId("10000");
        demo.setAge(25);
        demo.setName("roach");
        demo.setBirth(new Date());
        
        redisStringService.Object2JacksonSerializer(demo);
    }
    
    /**
     * 平均190ms左右
     * <br>
     * 在 REDIS 中查看可得知,日期已经转换为时间戳
     */
    @Test
    public void jacksonSerializer2Object(){
        StringDemo demo = redisStringService.jacksonSerializer2Object();
        System.out.println(demo);
    }
    
    /**
     * 85ms左右
     * <br>
     * 在 REDIS 中查看可得知,日期已经转换为时间戳
     */
    @Test
    public void object2FastjsonTest(){
        StringDemo demo = new StringDemo();
        demo.setId("10000");
        demo.setAge(25);
        demo.setName("roach");
        demo.setBirth(new Date());
        redisStringService.object2Fastjson(demo);
    }
    
    /**
     * 85ms左右
     */
    @Test
    public void fastjson2Object(){
        StringDemo demo = redisStringService.fastjson2Object();
        System.out.println(demo);
    }
}

3.3.3.2 JDK方式序列化实体

\xAC\xED\x00\x05sr\x007com.roachfu.study.module.string.model.entity.StringDemo\xA9\xD2^\x1FX\x99\xDD\xFA\x02\x00\x04I\x00\x03ageL\x00\x05birtht\x00\x10Ljava/util/Date;L\x00\x02idt\x00\x12Ljava/lang/String;L\x00\x04nameq\x00~\x00\x02xp\x00\x00\x00\x19sr\x00\x0Ejava.util.Datehj\x81\x01KYt\x19\x03\x00\x00xpw\x08\x00\x00\x01W\x03\xBF\xD8\xB5xt\x00\x0510000t\x00\x05roach

3.3.3.3 JSON方式序列化实体

将value序列化成JSON的方式又分两种:

(1) jackson序列化方式

public void Object2JacksonSerializer(StringDemo demo){
    Jackson2JsonRedisSerializer<StringDemo> jackson = new Jackson2JsonRedisSerializer<StringDemo>(StringDemo.class);
    redisTemplate.setValueSerializer(jackson);
    valueOperation.set("jackson2Object", demo);
}

(2) 直接将实体序列化成json的方式

public void object2Fastjson(StringDemo demo){
    String demoStr = JSON.toJSONString(demo);
    valueOps.set("fastjson2Object", demoStr);
}

3.3.3.4 总结

通过下面方法的验证,得出下面的结论:

(1) jdk方式执行的速度是最快的,但是由于存储的16进制字节序列,所占用的内存就比其他方式占用的多。

(2) jackson 这种序列化的方式最麻烦,代码的优雅度也相对较低,最惨的是执行的速度是最慢的。

(3) 直接转json方式(此处使用fastjson,其他的方式也是可以的。gson什么的)。写入的时候将javabean转成json,获取的时候又反序列成实体。这种方式比jdk方式慢点,比jackson方式快。

(4) jackson方式完败了(当然我的测试相对片面的),写出来的代码的可读性优雅度也没有其他两种好。

(5) 如果是公司的服务的内存强大,那就使用jdkSerializer这种方式。毕竟快。如果内存有限,那还是手动转json吧!

上一篇 下一篇

猜你喜欢

热点阅读