springboot+Lettuce+Protobuf+redis


Springboot統合redis選択
spring boot 2.x ; redis 5.0.x;protobuf 3.x;
目次
pom
コンフィギュレーション
->redis構成
->fastJsonTemplateConfig
ツールクラスの設定
JedisとLettuceの比較
pom
  • reids
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-redisartifactId>
    dependency>
    
  • FastJsonを使用してシーケンス化(オプション)
    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>fastjsonartifactId>
        <version>1.2.49version>
    dependency>
    
  • protobufを使用してシーケンス化(選択)
    <dependency>
        <groupId>com.baidugroupId>
        <artifactId>jprotobufartifactId>
        <version>2.2.9version>
    dependency>
    <dependency>
        <groupId>com.google.protobufgroupId>
        <artifactId>protobuf-javaartifactId>
        <version>3.6.0version>
    dependency>
    
    注意:異なるシーケンス化メカニズムを選択して使用することができ、この例ではfastjsonprotobufの2つを使用して実装する.本明細書で選択したprotobufのプラグインのgithubソース
  • コンフィギュレーション
  • redis構成とlettuce構成(jedisの区別は以下参照)
    spring.redis.database=0
    # Redis     
    spring.redis.host=192.168.137.128
    # Redis       
    spring.redis.port=6379
    # Redis       (    )
    spring.redis.password=123456
    #       (  )
    spring.redis.timeout=5000
    #         (          )
    spring.redis.lettuce.pool.max-active= 600
    #            (          )
    spring.redis.lettuce.pool.max-wait= -1
    #                 
    spring.redis.lettuce.pool.time-between-eviction-runs= 2000
    #            
    spring.redis.lettuce.pool.max-idle= 200
    #            
    spring.redis.lettuce.pool.min-idle=0
    
  • FastJson template構成
  • FastJsonを用いてシーケンス化を行い、Reidsのシーケンス化インターフェース
    public class FastJsonRedisSerializer<T> implements RedisSerializer<T> {
    	public static final Charset DEFAULT_UTF8 = Charset.forName("UTF-8");
    	private Class<T> tClass;
    
        public FastJsonRedisSerializer(Class<T> tClass) {
            super();
            this.tClass = tClass;
        }
    
        @Override
        public byte[] serialize(T t) throws SerializationException {
            if (ObjectUtils.isEmpty(t)){
                return new byte[0];
            }
            return JSONObject.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_UTF8);
        }
    
        @Override
        public T deserialize(byte[] bytes) throws SerializationException {
            if (ObjectUtils.isEmpty(bytes) || bytes.length == 0){
                return null;
            }
            String str = new String(bytes, DEFAULT_UTF8);
            return JSONObject.parseObject(str,tClass);
        }
    }
    
    
  • を実現する
  • カスタムredisテンプレート継承redisTemplate,
    
    @Component
    //          redis             RedisConnectionFactory (LettuceConnectionFactory)      
    @AutoConfigureAfter(RedisAutoConfiguration.class)
    @Import({RedisAutoConfiguration.class})
    @Slf4j
    public class FastJsonRedisTemplate extends RedisTemplate<String, Object> {
    
        public FastJsonRedisTemplate(
            @Value("#{'${IP.white.list}'.split(',')}") List<String> ipWhiteList,
            @Autowired() LettuceConnectionFactory lettuceConnectionFactory) {
            FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
            //    fastJson    
            ipWhiteList.stream().forEach(ipWhite -> ParserConfig.getGlobalInstance().addAccept(ipWhite));
            //     
            ParserConfig.getGlobalInstance().addAccept("com.study.www");
            setConnectionFactory(lettuceConnectionFactory);
            afterPropertiesSet();
            // key      StringRedisSerializer        
            setKeySerializer(stringRedisSerializer);
            setHashKeySerializer(stringRedisSerializer);
            setValueSerializer(fastJsonRedisSerializer);
            setHashValueSerializer(fastJsonRedisSerializer);
            logger.warn("the Lettuce-fastjson starting success,date is -->"+ new Date());
        }
    }
    
    
  • Protobuf template構成(オプション、FastJsonのシーケンス化スキームと1つ選択)
  • protobufを用いてシーケンス化を行い、Reidsのシーケンス化インターフェース(RedisSerializer)
    public class ProtobufRedisSerializer<T > implements RedisSerializer<T> {
        public static volatile Map<String, Codec> simpleTypeCodeMap = new HashMap<>();
        public static final Charset UTF8 = Charset.forName("UTF-8");
        private Class<T> tClass;
    
        public ProtobufRedisSerializer(Class<T> tClass) {
            super();
            this.tClass = tClass;
        }
    
        public ProtobufRedisSerializer(T t) {
            super();
            this.tClass = (Class<T>) t.getClass();
        }
    
        @Override
        public byte[] serialize(T t) throws SerializationException {
            Codec<T> codec = getCodec(t.getClass());
            try {
                return codec.encode(t);
            } catch (IOException e) {
                throw  new RuntimeException(e);
            }
        }
    
        @Override
        public T deserialize(byte[] bytes) throws SerializationException {
            if (ObjectUtils.isEmpty(bytes) || bytes.length == 0){
                return null;
            }
            try {
                Codec<T> codec = getCodec(tClass);
                return codec.decode(bytes);
            } catch (IOException e) {
                throw  new RuntimeException(e);
            }
        }
    
        private Codec<T> getCodec(Class clazz){
            Codec codec = simpleTypeCodeMap.get(clazz.getTypeName());
            if (ObjectUtils.isEmpty(codec)){
                synchronized (ProtobufRedisSerializer.class) {
                    codec = Optional.ofNullable(codec).orElseGet(() -> ProtobufProxy.create(clazz));
                    simpleTypeCodeMap.put(tClass.getTypeName(),codec);
                }
            }
            return codec;
        }
    }
    
  • を実現する
  • カスタムredisテンプレート継承redisTemplate,
    @Component
    @AutoConfigureAfter(RedisAutoConfiguration.class)
    @Import({RedisAutoConfiguration.class})
    @Slf4j
    public class ProtobufRedisTemplate extends RedisTemplate<String, Object> {
    
        public ProtobufRedisTemplate( @Autowired() LettuceConnectionFactory lettuceConnectionFactory) {
            ProtobufRedisSerializer protobufRedisSerializer = new ProtobufRedisSerializer(Object.class);
            StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
            setConnectionFactory(lettuceConnectionFactory);
            afterPropertiesSet();
            setKeySerializer(stringRedisSerializer);
            setHashKeySerializer(stringRedisSerializer);
            setValueSerializer(protobufRedisSerializer);
            setHashValueSerializer(protobufRedisSerializer);
            logger.warn("the Lettuce-protobuf starting success,date is -->"+ new Date());
        }
    }
    
  • 構築ツールクラス
    ```java
    @Component
    public class RedisUtils {
    
        @Autowired
        ProtobufRedisTemplate protobufRedisTemplate;
    
        ValueOperations operations = null;
        ListOperations operationsList = null;
        /***        72   = 259200S */
        private static final long TWODAY_TIME = 259200L;
    
        @PostConstruct
        public void init() {
            operations = protobufRedisTemplate.opsForValue();
            operationsList = protobufRedisTemplate.opsForList();
        }
    
        /**
        *         
        *
        * @param key key
        * @return Object
        */
        public Object get(String key) {
            if (ObjectUtils.isEmpty(key)) {
                return null;
            }
            return operations.get(key);
        }
    
        /**
        *         
        *
        * @param key   key
        * @param value value
        */
        public void set(String key, Object value) {
            if (!(ObjectUtils.isEmpty(key) || ObjectUtils.isEmpty(value))) {
                operations.set(key, value, TWODAY_TIME, TimeUnit.SECONDS);
            }
        }
    
        /**
        *         
        *
        * @param key    key
        * @param value  value
        * @param offset      S
        */
        public void set(String key, Object value, Long offset) {
            if (!(ObjectUtils.isEmpty(key) || ObjectUtils.isEmpty(value))) {
                offset = Optional.ofNullable(offset).orElseGet(() -> TWODAY_TIME);
                operations.set(key, value, offset, TimeUnit.SECONDS);
            }
        }
    
    
        /**
        *         
        *
        * @param key key
        */
        public void delete(String key) {
            if (!ObjectUtils.isEmpty(key)) {
                protobufRedisTemplate.delete(key);
            }
        }
    
    
        /**
        *   key    
        *
        * @param key  
        * @return true    false   
        */
        public boolean hasKey(String key) {
            if (!ObjectUtils.isEmpty(key)) {
                return protobufRedisTemplate.hasKey(key);
            }
            return false;
        }
    
        /**
        *   key         
        *
        * @param key  
        * @return   ( )   0       
        */
        public long getExpire(String key) {
            if (ObjectUtils.isEmpty(key)) {
                throw new RuntimeException("the redis key is not null!");
            }
            return protobufRedisTemplate.getExpire(key, TimeUnit.SECONDS);
        }
    
        /**
        *   list     
        *
        * @param key    
        * @param start   
        * @param end       0   -1     
        * @return List list      
        */
        public List lGet(String key, Long start, Long end) {
            if (ObjectUtils.isEmpty(key)) {
                throw new RuntimeException("the redis key is not null!");
            }
            start = Optional.ofNullable(start).orElseGet(() -> 0L);
            end = Optional.ofNullable(end).orElseGet(() -> -1L);
            return operationsList.range(key, start, end);
        }
    
        /**
        *   list  
        *
        * @param key    
        * @param value  
        */
        public void lPush(String key, Object value) {
            operationsList.leftPush(key, value);
        }
    
        /**
        *   list     
        * @param key  
        */
        public long lSize(String key){
            if (ObjectUtils.isEmpty(key)) {
                throw new RuntimeException("the redis key is not null!");
            }
            return operationsList.size(key);
        }
    }
    ```
    
    JedisとLettuce
    Jedis:I/Oブロック、メソッド同期呼び出し.これは線形実行であり、スレッドは安全ではありません.プールを接続して使用する必要があります
    Lettuce:Nettyに基づいて構築されたイベント駆動モデル、メソッド非同期呼び出し.そのスレッドは安全で、1つのLettuceをまとめると複数の操作を完了することができます.
    コード例csdn gitee