redis 与 序列化

概念

序列化:把对象转化为可传输的字节序列过程称为序列化。

反序列化:把字节序列还原为对象的过程称为反序列化。

 

为什么需要序列化

序列化最终的目的是为了对象可以跨平台存储,和进行网络传输。而我们进行跨平台存储和网络传输的方式就是IO,而我们的IO支持的数据格式就是字节数组。

因为我们单方面的只把对象转成字节数组还不行,因为没有规则的字节数组我们是没办法把对象的本来面目还原回来的,所以我们必须在把对象转成字节数组的时候就制定一种规则(序列化),那么我们从IO流里面读出数据的时候再以这种规则把对象还原回来(反序列化)。

如果我们要把一栋房子从一个地方运输到另一个地方去,序列化就是我把房子拆成一个个的砖块放到车子里,然后留下一张房子原来结构的图纸,反序列化就是我们把房子运输到了目的地以后,根据图纸把一块块砖头还原成房子原来面目的过程

 

什么情况下需要序列化

通过上面我想你已经知道了凡是需要进行“跨平台存储”和”网络传输”的数据,都需要进行序列化。

本质上存储和网络传输 都需要经过 把一个对象状态保存成一种跨平台识别的字节格式,然后其他的平台才可以通过字节信息解析还原对象信息。

 

序列化的方式

序列化只是一种拆装组装对象的规则,那么这种规则肯定也可能有多种多样,比如现在常见的序列化方式有:

JDK(不支持跨语言)、JSON、XML、Hessian、Kryo(不支持跨语言)、Thrift、Protostuff、FST(不支持跨语言)

 

Java  序列化

java 实现序列化很简单,只需要实现Serializable 接口即可。

public class User implements Serializable{
 //年龄
 private int age;
 //名字
 private String name ;

 public int getAge() {
 return age;
    }
 public void setAge(int age) {
 this.age = age;
    }

 public String getName() {
 return name;
    }

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

  

注意: JAVA序列化中常见的问题

  • 问题一:static 属性不能被序列化

 原因:序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量。

  • 问题二:Transient 属性不会被序列化
  • 问题三:序列化版本号serialVersionUID

 所有实现序列化的对象都必须要有个版本号,这个版本号可以由我们自己定义,当我们没定义的时候JDK工具会按照我们对象的属性生成一个对应的版本号。使用JDK生成的serialVersionUID,只要对象有一丁点改变serialVersionUID就会随着变更。因此建议自己手动定义该版本号。

 

Redis 序列化

当你用 Redis 的 key 和 value 时,value 对于 redis 来讲就是个 byte array。你要自己负责把你的内存中的数据结构转换成 byte array 存到 redis 中,等程序读取时再解析成相应的数据结构。

一个特例是字符串,因为字符串在内存中自己就已经是 byte array了,所以不需要自己处理。

Spring 的 redisTemplate 默认会使用 java serialization 做序列化。你也可以用 StringRedisTemplate,那么你 set的所有数据都会被 toString一下再存到 redis里。但这个 toString不一定能反解析的回来。如果使用 java原生序列化方式,可能会有远程代码执行问题,因此建议使用其他序列化方式代替。

233

参考文章


https://zhuanlan.zhihu.com/p/40462507

https://www.zhihu.com/question/277363840/answer/392945240

 

posted on 2019-06-25 10:41  Lemo_wd  阅读(7393)  评论(0编辑  收藏  举报

导航