Redis

1. 设置密码

  • config set requirepass 123456

  • config get requirepass


2. 登陆

2.1 linux

  • 开启服务,使用 redis-conf 的配置 :
    ./redis-server ../redis-conf

  • 开启数据库,使用密码 123456 登陆
    ./redis-cli -h 127.0.0.1 -p 6379 -a 123456

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


    org.springframework.data
    spring-data-redis
    1.7.2.RELEASE

3.1.2 配置RestTemplate


    
    
    



    
    
    
    
    
    



    

3.1.3 注入和使用RestTemplate

public class Example {

    // inject the actual template
    @Autowired
    private RedisTemplate template;

    // inject the template as ListOperations
    // can also inject as Value, Set, ZSet, and HashOperations
    @Resource(name="redisTemplate")
    private ListOperations 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获取得到。

Redis_第1张图片
123.png

3.3 序列化

  • spring-data-redis对key和value都有做序列化。相关序列化的方法在相应jar的org.springframework.data.redis.serializer包下面。

  • spring-data-redis 提供了很多张序列化的方法。序列化方式需要在配置文件中配置,如果没有配置,那么就使用默认的配置方式。

3.3.1 序列化配置


    
    
    
        
    
    
    
        
    
    
    
        
    
    
    
        
    
    
    
        
    

如果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 序列化方式

  • 这里讨论实体的序列化,如果只是String或者是基本类型的话,也就不需要上面那么多种策略了。

  • redis是key-value的nosql的内存数据库。对于java的实体而言,存储起来就有点麻烦。当然redis的hash是可以存储实体的,但是我们必须指定各个字段所对应的key。保存时将对应的实体属性一个个的放入hash,获取时,又得一个个的封装到实体。我们当然希望有更简单的方式。

  • 那么我们能想到的当然是json,xml什么的。xml就算了,我现在用xml的地方不多。所以我直接忽略了(如果以后用到了,那在说吧)。

  • 由上策略可知,我们转化的方式就是JdkSerializationRedisSerializer和Jackson2JsonRedisSerializer(xml方式不讨论)。以下就简称为json方式和jdk方式。

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 redisTemplate;
    
    private ValueOperations valueOperation;
    
    @Resource(name = "redisTemplate")
    private ValueOperations 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。所以在配置总不好配置,所以就在程序中手动配置。
     * 

* json的处理方式jackson是一种,还有的直接将实体转换成json,但是泛型的方式也要做相应的修改
* 至于使用哪一种来序列化。就随便了。fastjson、gson等等 */ @Override public void Object2JacksonSerializer(StringDemo demo){ Jackson2JsonRedisSerializer jackson = new Jackson2JsonRedisSerializer(StringDemo.class); redisTemplate.setValueSerializer(jackson); valueOperation.set("jackson2Object", demo); } @Override public StringDemo jacksonSerializer2Object(){ Jackson2JsonRedisSerializer jackson = new Jackson2JsonRedisSerializer(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
     * 

* 由上得出,以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左右 *
* 在 REDIS 中查看可得知,日期已经转换为时间戳 */ @Test public void jacksonSerializer2Object(){ StringDemo demo = redisStringService.jacksonSerializer2Object(); System.out.println(demo); } /** * 85ms左右 *
* 在 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方式序列化实体

  • 需要在相应的配置文件当中(例如在applicationContent.xml)配置valueSeriazer为JdkSerializationRedisSerializer。

  • 需要定义对应的实体泛型。

  • 这种序列化方式,是将value序列化成16进制的字节序列。比如一个实体StringDemo,序列化完之后的值为:

\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
  • 由上得出,以16进制保存的方式将实体的信息都保存了。可见占用的内存比较大。如果实体改变了包名,那么将不能反序列化。但是这种方式执行的效率比较高,速度比较快。

3.3.3.3 JSON方式序列化实体

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

(1) jackson序列化方式

  • 这是spring-data-redis自带方式,即Jackson2JsonRedisSerializer的实现方式。

  • 因为jackson的方式必须指定实体,所以在配置文件中配置会比较繁杂。所以一般都在方法总进行配置。比如

public void Object2JacksonSerializer(StringDemo demo){
    Jackson2JsonRedisSerializer jackson = new Jackson2JsonRedisSerializer(StringDemo.class);
    redisTemplate.setValueSerializer(jackson);
    valueOperation.set("jackson2Object", demo);
}
  • 如上可知,我们指定序列化StringDemo实体为json数据,在方法中定义了redisTemplate的valueSerializer,然后再存储数据。相比jdk的方式,代码上缺失了优雅性,需要同时设置redisTemplate和valueOperation。执行的速度也比jdk方式慢的多。

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

  • 这里使用fastjson进行javabean和json之间的转换,也可以使用其它的方式(gson,json-lib都是可以的)。

  • 这种方式是直接将javabean转换成json,返回的类型是String。valueSerializer需要设置成StringRedisSerializer。获取数据时,在通过fastjson将String转换成实体。

public void object2Fastjson(StringDemo demo){
    String demoStr = JSON.toJSONString(demo);
    valueOps.set("fastjson2Object", demoStr);
}
  • 如上所示:这种方式的代码优雅度比jackson方式高。经过测试,这种方式的执行效率比jackson高,比jdk方式低。

3.3.3.4 总结

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

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

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

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

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

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

你可能感兴趣的:(Redis)