使用Protostuff作为序列化机制,它的特点是:基于Protobuf、高效的编解码性能、以及和其他序列化框架相比Protostuff在序列化后字节码流更小,更易于传输及存储。 接下来进入正文…
jdk8, SpringBoot 2.1.9.RELEASE
本文所用源码已经上传github。
这里只做了简单的配置,其他相关配置自行查看源码或相关资料进行更改。
透过源码,可以发现每个序列化器都是继承自org.springframework.data.redis.serializer.RedisSerializer<T>接口
package org.springframework.data.redis.serializer; import org.springframework.lang.Nullable; ... public interface RedisSerializer<T> { /** * Serialize the given object to binary data. */ @Nullable byte[] serialize(@Nullable T t) throws SerializationException; /** * Deserialize an object from the given binary data. */ @Nullable T deserialize(@Nullable byte[] bytes) throws SerializationException; ... }因此只需要自定义一个继承自该接口的类,并实现serialize、deserialize即可。
package com.yorozuyas.demo.cache; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.SerializationException; import io.protostuff.LinkedBuffer; import io.protostuff.ProtostuffIOUtil; import io.protostuff.Schema; import io.protostuff.runtime.RuntimeSchema; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; /** * 使用Protostuff对value进行编解码。 */ public final class ProtostuffRedisSerializer implements RedisSerializer<Object> { final Schema<CacheValueWrapper> schema = RuntimeSchema.getSchema( CacheValueWrapper.class ); @Override public byte[] serialize( Object cvw ) throws SerializationException { try { return encode( cvw ); } catch ( RuntimeException e ) { throw new SerializationException( "Could not encode CacheValueWrapper to Protostuff: " + e.getMessage(), e ); } } @Override public Object deserialize( byte[] bytes ) throws SerializationException { try { return decode( bytes ); } catch ( RuntimeException e ) { throw new SerializationException( "Could not decode Protostuff to CacheValueWrapper: " + e.getMessage(), e ); } } // do serialize public byte[] encode( Object value ) { final LinkedBuffer buffer = LinkedBuffer.allocate(); return ProtostuffIOUtil.toByteArray( new CacheValueWrapper( value ), schema, buffer ); } // do deserialize public Object decode( byte[] bytes ) { CacheValueWrapper wrapper = new CacheValueWrapper(); ProtostuffIOUtil.mergeFrom( bytes, wrapper, schema ); return wrapper.getData(); } @AllArgsConstructor @NoArgsConstructor public static class CacheValueWrapper { @Getter private Object data; } }在源码org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration这个配置类中,可以看到注入了一个类型为RedisCacheManager的Bean,RedisCacheManager在创建过程中,调用determineConfiguration方法,并判断如果已经存在 org.springframework.data.redis.cache.RedisCacheConfiguration这个Bean,则直接返回,否则创建一个默认的org.springframework.data.redis.cache.RedisCacheConfiguration交给RedisCacheManager.
package org.springframework.boot.autoconfigure.cache; ... @Configuration @ConditionalOnClass(RedisConnectionFactory.class) @AutoConfigureAfter(RedisAutoConfiguration.class) @ConditionalOnBean(RedisConnectionFactory.class) @ConditionalOnMissingBean(CacheManager.class) @Conditional(CacheCondition.class) class RedisCacheConfiguration { private final CacheProperties cacheProperties; private final CacheManagerCustomizers customizerInvoker; private final org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration; RedisCacheConfiguration(CacheProperties cacheProperties, CacheManagerCustomizers customizerInvoker, ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration) { this.cacheProperties = cacheProperties; this.customizerInvoker = customizerInvoker; this.redisCacheConfiguration = redisCacheConfiguration.getIfAvailable(); } @Bean public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory, ResourceLoader resourceLoader) { RedisCacheManagerBuilder builder = RedisCacheManager.builder(redisConnectionFactory) .cacheDefaults(determineConfiguration(resourceLoader.getClassLoader())); List<String> cacheNames = this.cacheProperties.getCacheNames(); if (!cacheNames.isEmpty()) { builder.initialCacheNames(new LinkedHashSet<>(cacheNames)); } return this.customizerInvoker.customize(builder.build()); } private org.springframework.data.redis.cache.RedisCacheConfiguration determineConfiguration( ClassLoader classLoader) { if (this.redisCacheConfiguration != null) { return this.redisCacheConfiguration; } Redis redisProperties = this.cacheProperties.getRedis(); org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration .defaultCacheConfig(); config = config.serializeValuesWith( SerializationPair.fromSerializer(new JdkSerializationRedisSerializer(classLoader))); if (redisProperties.getTimeToLive() != null) { config = config.entryTtl(redisProperties.getTimeToLive()); } if (redisProperties.getKeyPrefix() != null) { config = config.prefixKeysWith(redisProperties.getKeyPrefix()); } if (!redisProperties.isCacheNullValues()) { config = config.disableCachingNullValues(); } if (!redisProperties.isUseKeyPrefix()) { config = config.disableKeyPrefix(); } return config; } }由于RedisCacheManager负责创建和管理各个RedisCache,并为各个RedisCache提供默认配置,包含序列化器,过期时间等。
package org.springframework.data.redis.cache; ... public class RedisCacheManager extends AbstractTransactionSupportingCacheManager { ... /** * Configuration hook for creating {@link RedisCache} with given name and {@code cacheConfig}. */ protected RedisCache createRedisCache(String name, @Nullable RedisCacheConfiguration cacheConfig) { return new RedisCache(name, cacheWriter, cacheConfig != null ? cacheConfig : defaultCacheConfig); } ... }因此我们只需要自定义一个org.springframework.data.redis.cache.RedisCacheConfiguration的Bean并交由Spring容器即可,后续在启动过程中,RedisCacheManager在创建的时候,会拿到我们注入到Spring中的RedisCacheConfiguration。
package com.yorozuyas.demo.cache; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration; import org.springframework.boot.autoconfigure.cache.CacheProperties; import org.springframework.boot.autoconfigure.cache.CacheProperties.Redis; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair; @Configuration @AutoConfigureAfter(CacheAutoConfiguration.class) @ConditionalOnProperty(name = "spring.cache.type", havingValue = "redis", matchIfMissing = false) public class RedisCacheAutoConfiguration { @Autowired private CacheProperties cacheProperties; /** * Custom {@link org.springframework.data.redis.cache.RedisCacheConfiguration} * * * @see org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration */ @Bean public RedisCacheConfiguration determineConfiguration() { final Redis redisProperties = cacheProperties.getRedis(); // Only open TTL, others close. RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .disableCachingNullValues() .disableKeyPrefix() // here, add custom ProtostuffRedisSerializer for value. .serializeValuesWith( SerializationPair.fromSerializer( new ProtostuffRedisSerializer() ) ); if ( redisProperties.getTimeToLive() != null ) { config = config.entryTtl( redisProperties.getTimeToLive() ); } return config; } }通常我们在买东西的时候,都需要一个明确的收件地址,而一个用户可以有多个收货地址。
运行redis,执行redis-cli进入redis并执行monitor监视连接请求。
运行MySQL,并执行初始化sql。
运行SpringBoot。
调用查询收货地址api
查看控制台输出信息,输出如下:
2020-07-04 19:43:45.752 14548 --- [ioEventLoop-4-1] DEBUG io.lettuce.core.RedisClient - Connecting to Redis at www.yorozuyas.com:6379: Success 2020-07-04 19:43:45.754 14548 --- [ioEventLoop-4-1] DEBUG io.lettuce.core.RedisChannelHandler - dispatching command AsyncCommand [type=AUTH, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.AsyncCommand] 2020-07-04 19:43:45.755 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.DefaultEndpoint - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, epid=0x1] write() writeAndFlush command AsyncCommand [type=AUTH, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.AsyncCommand] 2020-07-04 19:43:45.756 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] write(ctx, AsyncCommand [type=AUTH, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.AsyncCommand], promise) 2020-07-04 19:43:45.759 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandEncoder - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379] writing command AsyncCommand [type=AUTH, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.AsyncCommand] 2020-07-04 19:43:45.759 14548 --- [ioEventLoop-4-1] TRACE i.l.core.protocol.CommandEncoder - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379] Sent: *2 $4 AUTH $6 password 2020-07-04 19:43:45.762 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.DefaultEndpoint - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, epid=0x1] write() done 2020-07-04 19:43:45.762 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.ConnectionWatchdog - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, last known addr=www.yorozuyas.com/121.36.211.56:6379] userEventTriggered(ctx, io.lettuce.core.ConnectionEvents$Activated@8ff7c65) 2020-07-04 19:43:45.762 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.ConnectionWatchdog - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, last known addr=www.yorozuyas.com/121.36.211.56:6379] userEventTriggered(ctx, io.lettuce.core.ConnectionEvents$Activated@8ff7c65) 2020-07-04 19:43:45.769 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Received: 5 bytes, 1 commands in the stack 2020-07-04 19:43:45.769 14548 --- [ioEventLoop-4-1] TRACE i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Buffer: +OK 2020-07-04 19:43:45.769 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Stack contains: 1 commands 2020-07-04 19:43:45.769 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.RedisStateMachine - Decode AsyncCommand [type=AUTH, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.AsyncCommand] 2020-07-04 19:43:45.772 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.RedisStateMachine - Decoded AsyncCommand [type=AUTH, output=StatusOutput [output=OK, error='null'], commandType=io.lettuce.core.protocol.AsyncCommand], empty stack: true 2020-07-04 19:43:45.774 14548 --- [nio-8080-exec-2] DEBUG io.lettuce.core.RedisChannelHandler - dispatching command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 19:43:45.774 14548 --- [nio-8080-exec-2] DEBUG i.l.core.protocol.DefaultEndpoint - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, epid=0x1] write() writeAndFlush command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 19:43:45.775 14548 --- [nio-8080-exec-2] DEBUG i.l.core.protocol.DefaultEndpoint - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, epid=0x1] write() done 2020-07-04 19:43:45.775 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] write(ctx, AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command], promise) 2020-07-04 19:43:45.776 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandEncoder - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379] writing command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 19:43:45.776 14548 --- [ioEventLoop-4-1] TRACE i.l.core.protocol.CommandEncoder - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379] Sent: *2 $3 GET $16 address:zhangsan 2020-07-04 19:43:45.786 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Received: 5 bytes, 1 commands in the stack 2020-07-04 19:43:45.786 14548 --- [ioEventLoop-4-1] TRACE i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Buffer: $-1 2020-07-04 19:43:45.786 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Stack contains: 1 commands 2020-07-04 19:43:45.786 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.RedisStateMachine - Decode AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 19:43:45.786 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.RedisStateMachine - Decoded AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command], empty stack: true 2020-07-04 19:43:45.817 14548 --- [nio-8080-exec-2] DEBUG c.y.d.d.P.fetchAddress - ==> Preparing: SELECT id, uid, name, address, mobile FROM tb_deliver_address WHERE uid = ? 2020-07-04 19:43:45.834 14548 --- [nio-8080-exec-2] DEBUG c.y.d.d.P.fetchAddress - ==> Parameters: zhangsan(String) 2020-07-04 19:43:45.857 14548 --- [nio-8080-exec-2] DEBUG c.y.d.d.P.fetchAddress - <== Total: 4 2020-07-04 19:43:45.875 14548 --- [nio-8080-exec-2] DEBUG io.lettuce.core.RedisChannelHandler - dispatching command AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 19:43:45.876 14548 --- [nio-8080-exec-2] DEBUG i.l.core.protocol.DefaultEndpoint - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, epid=0x1] write() writeAndFlush command AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 19:43:45.876 14548 --- [nio-8080-exec-2] DEBUG i.l.core.protocol.DefaultEndpoint - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, epid=0x1] write() done 2020-07-04 19:43:45.876 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] write(ctx, AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command], promise) 2020-07-04 19:43:45.877 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandEncoder - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379] writing command AsyncCommand [type=SET, output=StatusOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 19:43:45.877 14548 --- [ioEventLoop-4-1] TRACE i.l.core.protocol.CommandEncoder - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379] Sent: *5 $3 SET $16 address:zhangsan $538 ? ArrayList?'com.yorozuyas.demo.model.DeliverAddresszhangsan鎴戠殑濮愬"-婀栧寳鐪佹姹夊競姹熸眽鍖哄彂灞曞ぇ閬?185鍙?(靖瘙-?'com.yorozuyas.demo.model.DeliverAddresszhangsan鎴戠殑濡瑰"6瀹夊窘鐪佸悎鑲ュ競缁忔祹鎶?鏈紑鍙戝尯鑺欒搲璺?678鍙?(扛瘙-?'com.yorozuyas.demo.model.DeliverAddresszhangsan鎴戠殑寮熷紵"9娴欐睙鐪佹澀宸炲競婊ㄦ睙鍖烘睙鍗楀ぇ閬撻緳婀栨花姹熷ぉ琛?(栏瘙-?'com.yorozuyas.demo.model.DeliverAddresszhangsan寮犱笁">骞夸笢鐪佷經灞卞競椤哄痉鍖哄ぇ鑹繋瀹捐矾纰ф鍥烽捇鐭虫咕(粮瘙- $2 PX $7 1800000从控制台可以看出,在请求过来之后,SpringCache注解起作用了,首先是执行登录请求,然后查询address:zhangsan,结果返回 Buffer: $-1,说明缓存中没有这条信息,那么就执行数据库查询操作,最后把查询结果添加到缓存中。
查看redis监控 可以看到先有一个登录请求过来,然后执行了GET查询操作,最后执行了SET添加操作,和上面分析一致。
再调用一次查询收货地址api
查看控制台输出
2020-07-04 20:13:36.682 14548 --- [nio-8080-exec-5] INFO c.y.d.c.Protobuf2RedisController - Request-Method: GET, Request-Path: /fetch, uid: zhangsan 2020-07-04 20:13:36.705 14548 --- [nio-8080-exec-5] DEBUG io.lettuce.core.RedisChannelHandler - dispatching command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 20:13:36.705 14548 --- [nio-8080-exec-5] DEBUG i.l.core.protocol.DefaultEndpoint - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, epid=0x1] write() writeAndFlush command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 20:13:36.706 14548 --- [nio-8080-exec-5] DEBUG i.l.core.protocol.DefaultEndpoint - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, epid=0x1] write() done 2020-07-04 20:13:36.706 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] write(ctx, AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command], promise) 2020-07-04 20:13:36.706 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandEncoder - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379] writing command AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 20:13:36.707 14548 --- [ioEventLoop-4-1] TRACE i.l.core.protocol.CommandEncoder - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379] Sent: *2 $3 GET $16 address:zhangsan 2020-07-04 20:13:36.715 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Received: 512 bytes, 1 commands in the stack 2020-07-04 20:13:36.715 14548 --- [ioEventLoop-4-1] TRACE i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Buffer: $538 ? ArrayList?'com.yorozuyas.demo.model.DeliverAddresszhangsan鎴戠殑濮愬"-婀栧寳鐪佹姹夊競姹熸眽鍖哄彂灞曞ぇ閬?185鍙?(靖瘙-?'com.yorozuyas.demo.model.DeliverAddresszhangsan鎴戠殑濡瑰"6瀹夊窘鐪佸悎鑲ュ競缁忔祹鎶?鏈紑鍙戝尯鑺欒搲璺?678鍙?(扛瘙-?'com.yorozuyas.demo.model.DeliverAddresszhangsan鎴戠殑寮熷紵"9娴欐睙鐪佹澀宸炲競婊ㄦ睙鍖烘睙鍗楀ぇ閬撻緳婀栨花姹熷ぉ琛?(栏瘙-?'com.yorozuyas.demo.model.DeliverAddresszhangsan寮犱笁">骞夸笢鐪佷經灞卞競椤哄痉鍖哄ぇ鑹繋瀹 2020-07-04 20:13:36.715 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Stack contains: 1 commands 2020-07-04 20:13:36.715 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.RedisStateMachine - Decode AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 20:13:36.715 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.RedisStateMachine - Decoded AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command], empty stack: false 2020-07-04 20:13:36.716 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Received: 34 bytes, 1 commands in the stack 2020-07-04 20:13:36.716 14548 --- [ioEventLoop-4-1] TRACE i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Buffer: 捐矾纰ф鍥烽捇鐭虫咕(粮瘙- 2020-07-04 20:13:36.716 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.CommandHandler - [channel=0xc4d24ef3, /192.168.3.16:50627 -> www.yorozuyas.com/121.36.211.56:6379, chid=0x1] Stack contains: 1 commands 2020-07-04 20:13:36.716 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.RedisStateMachine - Decode AsyncCommand [type=GET, output=ValueOutput [output=null, error='null'], commandType=io.lettuce.core.protocol.Command] 2020-07-04 20:13:36.716 14548 --- [ioEventLoop-4-1] DEBUG i.l.core.protocol.RedisStateMachine - Decoded AsyncCommand [type=GET, output=ValueOutput [output=[B@2e463c2d, error='null'], commandType=io.lettuce.core.protocol.Command], empty stack: true可以看到,执行了查询Redis,并得到结果Buffer: $538,然后就返回数据,没有执行数据库操作(没有打印SQL信息判断得知)。 另外,redis缓存的数据分别打印了两次,出现了Netty的读写半包,有兴趣的同学可以学习一下Netty,可参考《Netty权威指南》或《Netty实战》。
查看redis监控 监控得知,执行了查询操作,后面就没有其他输出信息了,证明查到数据了。其他接口就不再测试了,可自行进行测试。