redis-序列化:源码分析

607 阅读3分钟

流程

应用层

@Service
public class RedisService {
    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    public void set(String key, Object value,long time,TimeUnit timeunit) {
        //更改在redis里面查看key编码问题
        RedisSerializer redisSerializer =new StringRedisSerializer();
        redisTemplate.setKeySerializer(redisSerializer); //设置key的序列化类
        
        ValueOperations<String,Object> vo = redisTemplate.opsForValue();
        vo.set(key, value, time, timeunit);
    }

    public Object get(String key) {
        RedisSerializer redisSerializer =new StringRedisSerializer();
        redisTemplate.setKeySerializer(redisSerializer);
        ValueOperations<String,Object> vo = redisTemplate.opsForValue();
        return vo.get(key);
    }
}

数据存储在哪里?


核心业务逻辑
1.序列化
2.写数据到服务器

序列化,对象转字节数组。

写数据(刚刚序列化的字节数组)到服务器,这个是网络通信。

@Override
	public void set(K key, V value, long timeout, TimeUnit unit) {

		byte[] rawKey = rawKey(key);
		byte[] rawValue = rawValue(value); //序列化,得到字节数组

		execute(new RedisCallback<Object>() { //写数据到服务器

			@Override
			public Object doInRedis(RedisConnection connection) throws DataAccessException {

				potentiallyUsePsetEx(connection);
				return null;
			}

			public void potentiallyUsePsetEx(RedisConnection connection) {

				if (!TimeUnit.MILLISECONDS.equals(unit) || !failsafeInvokePsetEx(connection)) {
					connection.setEx(rawKey, TimeoutUtils.toSeconds(timeout, unit), rawValue);
				}
			}

			private boolean failsafeInvokePsetEx(RedisConnection connection) {

				boolean failed = false;
				try {
					connection.pSetEx(rawKey, timeout, rawValue);
				} catch (UnsupportedOperationException e) {
					// in case the connection does not support pSetEx return false to allow fallback to other operation.
					failed = true;
				}
				return !failed;
			}

		}, true);
	}

spring提供的序列化类

默认是jdk序列化类。


/**
	 * Serializes the source object and returns the byte array result.
	 */
	@Override
	public byte[] convert(Object source//输入数据) {
		ByteArrayOutputStream byteStream = new ByteArrayOutputStream(1024);
		try  {
			this.serializer.serialize(source, byteStream); //序列化,得到字节数组
			return byteStream.toByteArray();//输出数据
		}
		catch (Throwable ex) {
			throw new SerializationFailedException("Failed to serialize object using " +
					this.serializer.getClass().getSimpleName(), ex);
		}
	}

/**

	 * Writes the source object to an output stream using Java serialization.

	 * The source object must implement {@link Serializable}.

	 * @see ObjectOutputStream#writeObject(Object)

	 */

	@Override

	public void serialize(Object object, OutputStream outputStream) throws IOException {

		if (!(object instanceof Serializable)) { //校验对象是否实现可序列化类

			throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " +

					"but received an object of type [" + object.getClass().getName() + "]");

		}



		ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);

		objectOutputStream.writeObject(object); //对象转字节数组

		objectOutputStream.flush();

	}

jdk类

本质

序列化的本质,是对象转字节数组。和fastjson,对象转字符数组一样。二者没有本质区别。唯一的区别,就是,是否需要实现可序列化类。

fastjson,对象不需要实现可序列化类。其他的序列化,例如,jdk,google protobuf,对象要实现可序列化类。


测试代码

redis核心业务,就是下面的测试代码里包含的内容。

package gzh.test;



import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.ObjectOutputStream;



public class ObjectOutputStreamTest {



	public static void main(String[] args) {

		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);

		

		try {

			//存储数据的地方

			ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);

			

			//数据

			User user = new User();

			user.setName("gzh");

			user.setAge(20);

			

			//写数据:对象转字节数组

			objectOutputStream.writeObject(user);

		} catch (IOException e) {

			// TODO Auto-generated catch block

			e.printStackTrace();

		}

	}



}


序列化和非序列化的区别?

唯一的区别,就是是否实现序列化类。

序列化类,只是一个标志而已,没有什么具体的作用。唯一的作用,就是序列化类序列对象的时候,会校验对象是否实现可序列化类。


对象需要实现可序列化类,是因为序列化类会校验对象是否实现可序列化类,没有实现,会报错-对象没有实现可序列化类。



/**

	 * Writes the source object to an output stream using Java serialization.

	 * The source object must implement {@link Serializable}.

	 * @see ObjectOutputStream#writeObject(Object)

	 */

	@Override

	public void serialize(Object object //输入数据, OutputStream outputStream) throws IOException {

		if (!(object instanceof Serializable)) { //校验对象是否实现可序列化类

			throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " +

					"but received an object of type [" + object.getClass().getName() + "]");

		}



		ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream);

		objectOutputStream.writeObject(object); //对象转字节数组

		objectOutputStream.flush();

	}