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获取得到。
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){ Jackson2JsonRedisSerializerjackson = 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吧!