Redis

Redis is an open source (BSD-licensed), in-memory data structure storage system that can be used as a database, cache, and messaging middleware. It supports many types of data structures, such as strings (hashes), lists (Lists), sets (sets), sorted sets (sorted sets) and range queries, bitmaps, Hyperloglogs and Geospatial index radius query. Redis is built with replication, LUA scripting, LRU eviction, transactions and different levels of disk persistence, And provides high availability through Redis Sentinel and Automated partitioning (Cluster).

Redis is the most widely used in-memory data store in the industry today. Redis supports richer data structures than Memcached, such as hashes, lists, sets, etc., as well as data persistence.

In addition, Redis also provides database-like features such as transactions, HA, and master/slave libraries. It can be said that Redis has some characteristics of both cache system and database, so it has rich application scenarios. This paper introduces two typical application scenarios of Redis in Spring Boot.

Redis API is introduced

The Redis API provided by Spring Boot is divided into high-order API and low-order API. The high-order API is the API after certain encapsulation, while the use of the low-order API is similar to the command directly using Redis.

The advanced API provides two classes that we can use, RedisTemplate and StringRedisTemplate. StringRedisTemplate inherits from RedisTemplate, and StringRedisTemplate is serialized in a different way than RedisTemplate. The difference in usage is not particularly obvious, but the data stored in Redis is somewhat different due to the different serialization methods.

Low order apis are actually retrieved by either RedisTemplate or StringRedisTemplate. The low-level API approach is similar to the Redis command.

Redis serialization

1. What is serialization and deserialization

Serialization: Write an object to an IO stream

Deserialization: Recover objects from AN IO stream

Serialization significance: The serialization mechanism allows Java objects to be serialized into bit-byte sequences that can be stored on disk or transferred over the network for later restoration to the original object. Serialization allows objects to exist independently of program execution.

2, only need to configure, can solve the problem just appeared, but so many serialization means how to choose, I am curious, so I dug a little deeper:
/** * Description: Redis configuration */
@Configuration
public class MyRedisConfig {
    /** * redisTemplate configuration * serialization of several ways: * OxmSerializer * ByteArrayRedisSerializer * GenericJackson2JsonRedisSerializer * GenericToStringSerializer * StringRedisSerializer * JdkSerializationRedisSerializer * Jackson2JsonRedisSerializer *@paramRedisConnectionFactory Redis connection factory *@return RedisTemplate
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        // Configure the connection factory
        template.setConnectionFactory(redisConnectionFactory);
        // Set the serialization of the key
        template.setKeySerializer(new StringRedisSerializer());
        // Set the serialization method for value
        template.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
        returntemplate; }}Copy the code
The name of the instructions
ByteArrayRedisSerializer Array serialization
GenericJackson2JsonRedisSerializer Serialization using Jackson
GenericToStringSerializer Generalize an object to a string and serialize it, much like StringRedisSerializer
Jackson2JsonRedisSerializer Serialize the object to JSON using Jackson
JdkSerializationRedisSerializer The Serializable interface of the JDK is required to implement Serializable
OxmSerializer Store it in XML format
StringRedisSerializer Simple string serialization
3. Compare the differences between several common serialization methods
@SpringBootTest
class CacheApplicationTests {

    /** * Test the efficiency of several serialization methods */
    @Test
    void test(a) {
        User user = new User();
        user.setId(1);
        user.setUsername("Zhang");
        user.setPassword("123");
        List<Object> list = new ArrayList<>();

        for (int i = 0; i < 2000; i++) {
            list.add(user);
        }
        
        
        / / use GenericJackson2JsonRedisSerializer serialization (efficiency is too low, not recommended)
        GenericJackson2JsonRedisSerializer g2 = new GenericJackson2JsonRedisSerializer();
        long g2s = System.currentTimeMillis();
        byte[] byteG2 = g2.serialize(list);
        long g2l = System.currentTimeMillis();
        System.out.println("GenericJackson2JsonRedisSerializer serialization consumption of time." + (g2l - g2s) + "Ms, serialized length:" + byteG2.length);
        g2.deserialize(byteG2);
        System.out.println(The time of the "GenericJackson2JsonRedisSerializer deserialization:" + (System.currentTimeMillis() - g2l) + "ms");

        / / use GenericToStringSerializer serialization (similar to StringRedisSerializer, high efficiency without StringRedisSerializer, not recommended)
        GenericToStringSerializer g = new GenericToStringSerializer(Object.class);

        long gs = System.currentTimeMillis();
        byte[] byteG = g.serialize(list.toString());
        long gl = System.currentTimeMillis();
        System.out.println("GenericToStringSerializer serialization consumption of time." + (gl - gs) + "Ms, serialized length:" + byteG.length);
        g.deserialize(byteG);
        System.out.println(The time of the "GenericToStringSerializer deserialization:" + (System.currentTimeMillis() - gl) + "ms");


        / / use Jackson2JsonRedisSerializer serialization (serialization) for high efficiency and value of the value
        Jackson2JsonRedisSerializer j2 = new Jackson2JsonRedisSerializer(Object.class);
        long j2s = System.currentTimeMillis();
        byte[] byteJ2 = j2.serialize(list);
        long j2l = System.currentTimeMillis();
        System.out.println("Jackson2JsonRedisSerializer serialization consumption of time." + (j2l - j2s) + "Ms, serialized length:" + byteJ2.length);
        j2.deserialize(byteJ2);
        System.out.println(The time of the "Jackson2JsonRedisSerializer deserialization:" + (System.currentTimeMillis() - j2l) + "ms");

        
        / / use JdkSerializationRedisSerializer, entity class must implement the serializable interface (not recommended)
        JdkSerializationRedisSerializer j = new JdkSerializationRedisSerializer();
        long js = System.currentTimeMillis();
        byte[] byteJ = j.serialize(list);
        long jl = System.currentTimeMillis();
        System.out.println("JdkSerializationRedisSerializer serialization consumption of time." + (jl - js) + "Ms, serialized length:" + byteJ.length);
        j.deserialize(byteJ);
        System.out.println(The time of the "JdkSerializationRedisSerializer deserialization:" + (System.currentTimeMillis() - jl) + "ms");


        // Use StringRedisSerializer for serialization.
        StringRedisSerializer s = new StringRedisSerializer();

        long ss = System.currentTimeMillis();
        byte[] byteS = s.serialize(list.toString());
        long sl = System.currentTimeMillis();
        System.out.println("StringRedisSerializer takes time to serialize:" + (sl - ss) + "Ms, serialized length:" + byteS.length);
        s.deserialize(byteS);
        System.out.println("StringRedisSerializer deserialization time:" + (System.currentTimeMillis() - sl) + "ms");


        // Use FastJson for serialization
        FastJsonRedisSerializer<Object> f = new FastJsonRedisSerializer<>(Object.class);

        long fs = System.currentTimeMillis();
        byte[] byteF = f.serialize(list);
        long fl = System.currentTimeMillis();
        System.out.println("FastJsonRedisSerializer takes time to serialize:" + (fl - fs) + "Ms, serialized length:" + byteF.length);
        f.deserialize(byteF);
        System.out.println("FastJsonRedisSerializer deserialization time:" + (System.currentTimeMillis() - fl) + "ms");


        // Use FastJson(high efficiency, small footprint after serialization, recommended)
        GenericFastJsonRedisSerializer gf = new GenericFastJsonRedisSerializer();

        long gfs = System.currentTimeMillis();
        byte[] byteGf = gf.serialize(list);
        long gfl = System.currentTimeMillis();
        System.out.println("GenericFastJsonRedisSerializer serialization consumption of time." + (gfl - gfs) + "Ms, serialized length:" + byteGf.length);
        gf.deserialize(byteGf);
        System.out.println(The time of the "GenericFastJsonRedisSerializer deserialization:" + (System.currentTimeMillis() - gfl) + "ms"); }}Copy the code
4, summarize
The name of the Serialization efficiency Deserialization efficiency Take up the space Is it recommended?
StringRedisSerializer high high high Serialization for keys is recommended
Jackson2JsonRedisSerializer high higher On the high side Serialization for value is recommended
GenericFastJsonRedisSerializer high The lower The lower Serialization for value is recommended
5. Attach the Redis serialization configuration file
/ * * *@Description: Redis configuration */
@Configuration
public class MyRedisConfig {
    /** * redisTemplate configuration *@paramRedisConnectionFactory Redis connection factory *@return RedisTemplate
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        // Configure the connection factory
        template.setConnectionFactory(redisConnectionFactory);
        // Set the serialization of the key
        template.setKeySerializer(new StringRedisSerializer());
        / / use Jackson2JsonRedisSerializer configuration value way of serialization
        template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
        // Use FastJson to serialize value
// template.setValueSerializer(new GenericFastJsonRedisSerializer());
        returntemplate; }}Copy the code

Encapsulate the RedisUtils utility class

Introduce Redis dependencies
<! --SpringBoot and Redis integrate dependencies -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Copy the code
Set the Redis Template — > redisconfig.java
/ * * *@Description: Redis configuration class */
@Configuration
public class RedisConfig {
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        redisTemplate.setConnectionFactory(factory);

        // Key serialization
        redisTemplate.setKeySerializer(redisSerializer);
        // value serializes
        redisTemplate.setValueSerializer(redisSerializer);
        // Key hashMap serialization
        redisTemplate.setHashKeySerializer(redisSerializer);
        // value hashMap serialization
        redisTemplate.setHashValueSerializer(redisSerializer);
        returnredisTemplate; }}Copy the code
Setting Connection Information
#Redis
# which database to connect to
spring.redis.database=0
Redis service IP address
spring.redis.host=127.0.0.1
# redis port number
spring.redis.port=6379
# redis password, not set password, can be empty
spring.redis.password=ycfxhsw
Copy the code
Redis tools
/** * Redis utility class */
@Service
public class RedisUtils {
    @Autowired
    private RedisTemplate redisTemplate;

    private static double size = Math.pow(2.32);

    /** * write cache *@param key
     * @param offset
     * @param isShow
     * @return result
     */
    public boolean setBit(String key, long offset, boolean isShow) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.setBit(key, offset, isShow);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /** * write cache *@param key
     * @param offset
     * @return result
     */
    public boolean getBit(String key, long offset) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            result = operations.getBit(key, offset);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /** * write cache *@param key
     * @param value
     * @return* /
    public boolean set(final String key, Object value) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /** * Write cache set aging time *@param key
     * @param value
     * @return* /
    public boolean set(final String key, Object value, Long expireTime) {
        boolean result = false;
        try {
            ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
            operations.set(key, value);
            redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /** * Delete the corresponding value * in batches@param keys
     */
    public void remove(final String... keys) {
        for(String key : keys) { remove(key); }}/** * delete the corresponding value *@param key
     */
    public void remove(final String key) {
        if(exists(key)) { redisTemplate.delete(key); }}/** * Check whether the corresponding value * exists in the cache@param key
     * @return* /
    public boolean exists(final String key) {
        return redisTemplate.hasKey(key);
    }

    /** * read cache *@param key
     * @return* /
    public Object get(final String key) {
        Object result = null;
        ValueOperations<Serializable, Object> operations = redisTemplate.opsForValue();
        result = operations.get(key);
        return result;
    }

    /** * hash to add *@param key
     * @param hashKey
     * @param value
     */
    public void hmSet(String key, Object hashKey, Object value) {
        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
        hash.put(key, hashKey, value);
    }

    /** * hash to get data *@param key
     * @param hashKey
     * @return* /
    public Object hmGet(String key, Object hashKey) {
        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
        return hash.get(key, hashKey);
    }

    /** * add * to list@param k
     * @param v
     */
    public void lPush(String k, Object v) {
        ListOperations<String, Object> list = redisTemplate.opsForList();
        list.rightPush(k, v);
    }

    /** * List gets *@param k
     * @param l
     * @param l1
     * @return* /
    public List<Object> lRange(String k, long l, long l1) {
        ListOperations<String, Object> list = redisTemplate.opsForList();
        return list.range(k, l, l1);
    }

    /** * add * to collection@param key
     * @param value
     */
    public void add(String key, Object value) {
        SetOperations<String, Object> set = redisTemplate.opsForSet();
        set.add(key, value);
    }

    /** * the collection gets *@param key
     * @return* /
    public Set<Object> setMembers(String key) {
        SetOperations<String, Object> set = redisTemplate.opsForSet();
        return set.members(key);
    }

    /** * ordered collection adds *@param key
     * @param value
     * @param scoure
     */
    public void zAdd(String key, Object value, double scoure) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        zset.add(key, value, scoure);
    }

    /** * The ordered collection gets *@param key
     * @param scoure
     * @param scoure1
     * @return* /
    public Set<Object> rangeByScore(String key, double scoure, double scoure1) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        redisTemplate.opsForValue();
        return zset.rangeByScore(key, scoure, scoure1);
    }


    /** * Load data into Redis for the first time@param name
     */
    public void saveDataToRedis(String name) {
        double index = Math.abs(name.hashCode() % size);
        long indexLong = new Double(index).longValue();
        boolean availableUsers = setBit("availableUsers", indexLong, true);
    }

    /** * Load data into Redis for the first time@param name
     * @return* /
    public boolean getDataToRedis(String name) {
        double index = Math.abs(name.hashCode() % size);
        long indexLong = new Double(index).longValue();
        return getBit("availableUsers", indexLong);
    }

    /** * The ordered collection gets the rank *@paramKey Set name *@paramThe value value * /
    public Long zRank(String key, Object value) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        return zset.rank(key, value);
    }


    /** * The ordered collection gets the rank *@param key
     */
    public Set<ZSetOperations.TypedTuple<Object>> zRankWithScore(String key, long start, long end) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        Set<ZSetOperations.TypedTuple<Object>> ret = zset.rangeWithScores(key, start, end);
        return ret;
    }

    /** * ordered collection adds *@param key
     * @param value
     */
    public Double zSetScore(String key, Object value) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        return zset.score(key, value);
    }


    /** * Add score * to ordered set@param key
     * @param value
     * @param scoure
     */
    public void incrementScore(String key, Object value, double scoure) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        zset.incrementScore(key, value, scoure);
    }


    /** * The ordered collection gets the rank *@param key
     */
    public Set<ZSetOperations.TypedTuple<Object>> reverseZRankWithScore(String key, long start, long end) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        Set<ZSetOperations.TypedTuple<Object>> ret = zset.reverseRangeByScoreWithScores(key, start, end);
        return ret;
    }

    /** * The ordered collection gets the rank *@param key
     */
    public Set<ZSetOperations.TypedTuple<Object>> reverseZRankWithRank(String key, long start, long end) {
        ZSetOperations<String, Object> zset = redisTemplate.opsForZSet();
        Set<ZSetOperations.TypedTuple<Object>> ret = zset.reverseRangeWithScores(key, start, end);
        returnret; }}Copy the code
test
@RestController
public class RedisController {
    @Autowired
    private RedisUtils redisUtils;

    @RequestMapping("setAndGet")
    public String test(String k, String v) {
        redisUtils.set(k, v);
        return(String) redisUtils.get(k); }}Copy the code