Redis的jdk和json序列化性能对比

              redis默认采用的序列化策略有两种,一种是String的序列化策略,一种是JDK的序列化策略.    
              
               
              有一下几个序列化工具类:

				1. GenericToStringSerializer: 可以将任何对象泛化为字符串并序列化
   				2. Jackson2JsonRedisSerializer: 跟JacksonJsonRedisSerializer实际上是一样的
   				3. JacksonJsonRedisSerializer: 序列化object对象为json字符串
   				4. JdkSerializationRedisSerializer: 序列化java对象(被序列化的对象必须实现Serializable接口),无法转义成对象
   				5.StringRedisSerializer: 简单的字符串序列化
   				6. GenericToStringSerializer:类似StringRedisSerializer的字符串序列化

			GenericJackson2JsonRedisSerializer:类似Jackson2JsonRedisSerializer,但使用时构造函数不用特定的类参考以上序列化,自定义序
			版权声明:本文为CSDN博主「向着高亮的地方前行」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
			原文链接:https://blog.csdn.net/y532798113/article/details/82690781                                     

下面对比jdk.json.hash序列化10W个对象的性能

				/**
					 * 使用JDK系列化方式保存十万个user随机对象到Redis,并计算耗时
				 	 * @return
				 */
				@RequestMapping("serializableUserInJDK")
				public String serializableUserInJDK(Model model) {
					//配置jdk序列化工具
					redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
					
					//创建list模版对象
					ListOperations opsForList = redisTemplate.opsForList();
					
					long time = System.currentTimeMillis();
					//遍历存储
					for (int i = 0; i < 100000; i++) {
						User user = new User(i,ChineseName.getName(),getSex(),RandomNumber.getPhone("13"),getEmail(),getAge());
						opsForList.leftPush("jdkUser"+i, user);
					}
					
					model.addAttribute("message", "jdk");
					model.addAttribute("time", System.currentTimeMillis() - time);
					return "show";
				}

		

					**jdk格式序列化完毕,用时:56464ms**

			/**
				 * 使用JSON系列化方式保存十万个user随机对象到Redis,并计算耗时
				 * @return
			 */
				@RequestMapping("serializableUserInJSON")
				public String serializableUserInJSON(Model model) {
					//配置json序列化工具
					redisTemplate.setValueSerializer(new Jackson2JsonRedisSerializer<>(User.class));
					
					ListOperations opsForList = redisTemplate.opsForList();
					
					long time = System.currentTimeMillis();
					
					for (int i = 0; i < 100000; i++) {
						User user = new User(i,ChineseName.getName(),getSex(),RandomNumber.getPhone("13"),getEmail(),getAge());
						Object json = JSON.toJSON(user);
						opsForList.leftPush("jsonUser"+i, json);
					}
					
					model.addAttribute("message", "json");
					model.addAttribute("time", System.currentTimeMillis() - time);
					return "show";
				}
			       **json格式序列化完毕,用时:56703ms**

			/**
			  * 使用Redis的Hash类型保存十万个user随机对象到Redis,并计算耗时
			  * @return
			 */
			@RequestMapping("serializableUserInHash")
			public String serializableUserInHash(Model model) {
				//配置hash序列化工具
				redisTemplate.setHashValueSerializer(new StringRedisSerializer());
				redisTemplate.setHashKeySerializer(new StringRedisSerializer());
				
				HashOperations opsForList = redisTemplate.opsForHash();
				
				long time = System.currentTimeMillis();
				
				for (int i = 0; i < 100000; i++) {
					User user = new User(i,ChineseName.getName(),getSex(),RandomNumber.getPhone("13"),getEmail(),getAge());
					opsForList.put("hashUser", "user"+i, user.toString());
				}
				
				model.addAttribute("message", "Hash");
				model.addAttribute("time", System.currentTimeMillis() - time);
				return "show";
			}
				**Hash格式序列化完毕,用时:56519ms**
  • 10W条数据对比差异不大,从执行时间上来看,JdkSerializationRedisSerializer是最高效的(毕竟是JDK原生的),但是是序列化的结果字符串是最长的。JSON由于其数据格式的紧凑性,序列化的长度是最小的,时间比前者要多一些。而OxmSerialiabler在时间上看是最长的(当时和使用具体的Marshaller有关)。所以个人的选择是倾向使用JacksonJsonRedisSerializer作为POJO的序列器。

版权声明:本文为CSDN博主「keke_xin」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/keke_Xin/article/details/84708633


								## 管道测试(前言引用前辈,想深入了解点击下面连接)

Redis的pipeline(管道)功能在命令行中没有,但redis是支持pipeline的,而且在各个语言版的client中都有相应的实现。 由于网络开销延迟,就算redis server端有很强的处理能力,也会由于收到的client消息少,而造成吞吐量小。当client 使用pipelining 发送命令时,redis server必须将部分请求放到队列中(使用内存),执行完毕后一次性发送结果;如果发送的命令很多的话,建议对返回的结果加标签,当然这也会增加使用的内存;

Pipeline在某些场景下非常有用,比如有多个command需要被“及时的”提交,而且他们对相应结果没有互相依赖,对结果响应也无需立即获得,那么pipeline就可以充当这种“批处理”的工具;而且在一定程度上,可以较大的提升性能,性能提升的原因主要是TCP连接中减少了“交互往返”的时间。

不过在编码时请注意,pipeline期间将“独占”链接,此期间将不能进行非“管道”类型的其他操作,直到pipeline关闭;如果你的pipeline的指令集很庞大,为了不干扰链接中的其他操作,你可以为pipeline操作新建Client链接,让pipeline和其他正常操作分离在2个client中。不过pipeline事实上所能容忍的操作个数,和socket-output缓冲区大小/返回结果的数据尺寸都有很大的关系;同时也意味着每个redis-server同时所能支撑的pipeline链接的个数,也是有限的,这将受限于server的物理内存或网络接口的缓冲能力。

版权声明:本文为CSDN博主「BugFree_张瑞」的原创文章,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011489043/article/details/78769428

/**
	 * 使用 管道 JDK 系列化方式将十万个 user 对象保存到 Redis
	 * 
	 */
	@RequestMapping("serializableUserInJDK")
	public String serializableUserInJDK() {
		
		redisTemplate.executePipelined(new SessionCallback() {
			@Override
			public  Object execute(RedisOperations operations) throws DataAccessException {
				
				long time = System.currentTimeMillis();
				for (int i = 0; i < 100000; i++) {
					 User user = new User(ChineseName.getName(),RandomNumber.getPhone("180"));
					 redisTemplate.opsForList().leftPush("pipJdkUser"+i, user);
				}
				System.out.println("用时:"+(System.currentTimeMillis()-time));
				return null;
			}
		});
		return null;
	}
	用时:1795ms
 
  
	    /**
	    	 * 使用 JSON 系列化方式将十万个 user 对象保存到 Redis
	    	 */
	    	@RequestMapping("serializableUserInJsonPip")
	    	public String serializableUserInJsonPip() {
	    		redisTemplate.executePipelined(new SessionCallback() {
	    			@Override
	    			public  Object execute(RedisOperations operations) throws DataAccessException {
	    				long time = System.currentTimeMillis();
	    				for (int i = 0; i < 1000000; i++) {
	    					User user = new User(ChineseName.getName(),RandomNumber.getPhone("180"));
	    					Object json = JSON.toJSON(user);
	    					redisTemplate.opsForList().leftPush("pipJson"+i, json);
	    				}
	    				System.out.println("耗时:"+(System.currentTimeMillis()-time));
	    				return null;
	    			}
	    		});
	    		return null;
	    	}
	    	耗时:3653ms
 
  
/**
 * 使用 Redis 的 Hash 类型保存十万个 user 对象,测试所耗时间。
 */
@RequestMapping("serializeUserInHash")
public void serializeUserInHash() {
	redisTemplate.executePipelined(new SessionCallback() {
		@Override
		public  Object execute(RedisOperations operations) throws DataAccessException {
			long time = System.currentTimeMillis();
			for (int i = 0; i < 100000; i++) {
				User user = new User(ChineseName.getName(),RandomNumber.getPhone("180"));
				Object json = JSON.toJSON(user);
				redisTemplate.opsForHash().put("hashUser","user"+i , json);
			}
			System.out.println("耗时:"+(System.currentTimeMillis() - time));
			return null;
		}
	});
}
耗时:3069ms
---
 
  

使用管道可以发现性能有明显的提高,在之前的性能十倍之上.但是也并不是管道用的越多越好,详情参考"CSDN博主「BugFree_张瑞」"的详细介绍

总而言之,序列化方式的性能还是根据具体开发情况来定,合理的运用好redis会让性能加倍提高.
本次测试10w条数据,8G运行内存刚刚够用.如果测试要把之前redis里的缓存清空再进行,不然可能会对结果有影响.

第一次发贴,多多指教.

你可能感兴趣的:(redis)