Tag Archives: redis

Redis: How to Configurate Redis.conf File

The configuration file is case insensitive

Other configuration files can be included

###Network-related###
# bind 127.0.0.1 # Bind the listening NIC IP, comment out or configure to 0.0.0.0 to make any IP accessible

protected-mode yes # Turn off protected mode, use password access

port 6379 # Set the listening port, it is recommended that production environments use custom ports

timeout 30 # how long the client connection is idle before disconnecting, in seconds, 0 means disabled

###General configuration###
daemonize yes # default is no, run in the background as a daemon

pidfile /var/run/redis_6379.pid # If running in the background, specify the pid process file name

### log###
# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important/critical messages are logged)
loglevel notice

logfile "" # file name of the log

databases 16 # number of databases default is 16 databases

always-show-logo yes # Whether to show logs, default is no

### RDB persistence configuration ###
### redis is memory-based, no persistence, data disappears if power is lost
save 900 1 # bgsave for RDB persistence if at least one write operation in 900s
save 300 10
save 60 10000 

stop-writes-on-bgsave-error yes # Whether to continue working after persistence errors

rdbcompression yes # whether to compress the rdb file requires CPU consumption recommend setting to no, to exchange (disk) space for (CPU) time

rdbchecksum yes # whether to save the rdb file for checking

dbfilename dump.rdb # rdb file name

dir . / # rdb file save directory

###AOF configuration###
appendonly yes # The default value is no, which means do not use the AOF incremental persistence method, use the RDB full persistence method
appendfsync everysec # optional values always, everysec, no, suggest to set to everysec

### set password###
requirepass 123456 # Set a more complex password

###Clients###
maxclients 10000 # Maximum number of client connections

maxmemory <bytes> # redis sets the maximum memory capacity

maxmemory-policy noeviction # Policy for handling memory when it reaches the upper limit
1, volatile-lru: LRU only for keys with expiration time set (default)
2、allkeys-lru : remove the key of lru algorithm
3, volatile-random: randomly delete the key that is about to expire
4、allkeys-random:randomly delete
5、volatile-ttl : Delete the soon to expire
6、noeviction : Never expire, return error

###APPEND ONLY MODE aof configuration###
appendonly no # default does not enable aof mode, the default is to use rdb way persistent

appendfilename "appendonly.aof" # Persistent file name

# appendfsync always # sync every time you make a change, which consumes performance
appendfsync everysec # execute sync every second, but may lose this 1s data
# appendfsync no # no sync, OS syncs data itself, fastest

Ysec # executes sync once per second, but the 1s data may be lost

Appendfsync no # if you don’t execute sync, the operating system synchronizes data by itself, and the speed is the fastest


[Solved] Consider defining a bean of type ‘org.springframework.data.redis.core.RedisTemplate‘ in your configu

Today, I only added this paragraph to find that the project can’t start

@Autowired
private RedisTemplate<String, Object> template;

Project error report

Description:

Field template in com.yy.service.impl.YuumiUserServiceImpl required a bean of type 'org.springframework.data.redis.core.RedisTemplate' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)


Action:

Consider defining a bean of type 'org.springframework.data.redis.core.RedisTemplate' in your configuration.

Solution:
Add Class

package com.yy.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component; 

@Component
public class Config {

    @Bean(name = "template")
    public RedisTemplate<String, Object> template(RedisConnectionFactory factory) {
        // create RedisTemplate<String, Object>
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        // Configuring the connection factory
        template.setConnectionFactory(factory);
        // Define the Jackson2JsonRedisSerializer serialization object
        Jackson2JsonRedisSerializer<Object> jacksonSeial = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper om = new ObjectMapper();
        // Specify the fields to serialize, field, get and set, and the range of modifiers, ANY is both private and public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // Specify the type of serialized input, the class must be non-final modified, final modified class, such as String, Integer, etc. will report an exception
        om.activateDefaultTyping(

                LaissezFaireSubTypeValidator.instance ,
                ObjectMapper.DefaultTyping.NON_FINAL,

                JsonTypeInfo.As.WRAPPER_ARRAY);
        jacksonSeial.setObjectMapper(om);
        StringRedisSerializer stringSerial = new StringRedisSerializer();
        // redis key Serialization method using stringSerial
        template.setKeySerializer(stringSerial);
        // redis value serialization method using jackson
        template.setValueSerializer(jacksonSeial);
        // redis hash key serialized using stringSerial
        template.setHashKeySerializer(stringSerial);
        // redis hash value serialized using jackson
        template.setHashValueSerializer(jacksonSeial);
        template.afterPropertiesSet();
        return template;
    }
}

The project runs successfully

Connection error:Cannot connect to redis-server. Details are available in connection log.

The redis process has not started, and the following situation occurs

reloads the configuration, and the directory does not use the absolute path to restart. My redis is installed in the pagoda
redis.conf in the/www/server/redis directory

redis server in the/www/server/redis/SRC directory

Restart profile

/www/server/redis/src/redis-server /www/server/redis/redis.conf

Profile validation

Error reported when springboot connects to redis nested exception is redis.clients.jedis . exceptions.JedisConnectionException

The error message is as follows.
Severe :Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.data.redis. RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions. JedisConnectionException: Could not get a resource from the pool] with root cause
Because the ip address on the linux system in the virtual machine has changed, the configuration file in springboot has forgotten to change it.
Enter [root@localhost bin]# ip addr to see the ip address
Just change the configuration file
spring.redis.host=

Springboot integrates redis factory method ‘redisconnectionfactory’ threw exception; nested exception is

Factory method ‘redisConnectionFactory’ threw exception; nested exception is java.lang. NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
springboot integration redis error

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisUtil': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'redisTemplate' defined in class path resource [com/fhlkd/config/RedisConfig.class]: Unsatisfied dependency expressed through method 'redisTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisConnectionFactory' defined in class path resource [org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory]: Factory method 'redisConnectionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:337)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1429)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:594)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:879)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
	at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:125)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:99)
	at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
	... 63 more
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'redisTemplate' defined in class path resource [com/fhlkd/config/RedisConfig.class]: Unsatisfied dependency expressed through method 'redisTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisConnectionFactory' defined in class path resource [org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory]: Factory method 'redisConnectionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:787)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:528)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:207)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:454)
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:543)
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:513)
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:653)
	at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:224)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:116)
	at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:334)
	... 79 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisConnectionFactory' defined in class path resource [org/springframework/boot/autoconfigure/data/redis/LettuceConnectionConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory]: Factory method 'redisConnectionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:645)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:625)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1338)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:557)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1287)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1207)
	at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:874)
	at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:778)
	... 95 more
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory]: Factory method 'redisConnectionFactory' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:640)
	... 109 more
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/pool2/impl/GenericObjectPoolConfig
	at org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration$LettucePoolingClientConfigurationBuilder.<init>(LettucePoolingClientConfiguration.java:94)
	at org.springframework.data.redis.connection.lettuce.LettucePoolingClientConfiguration.builder(LettucePoolingClientConfiguration.java:51)
	at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration$PoolBuilderFactory.createBuilder(LettuceConnectionConfiguration.java:136)
	at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration.createBuilder(LettuceConnectionConfiguration.java:100)
	at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration.getLettuceClientConfiguration(LettuceConnectionConfiguration.java:86)
	at org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration.redisConnectionFactory(LettuceConnectionConfiguration.java:68)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
	... 110 more
Caused by: java.lang.ClassNotFoundException: org.apache.commons.pool2.impl.GenericObjectPoolConfig
	at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	... 121 more


because no corresponding JARs found
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

Termux installing redis

When I compile and install redis under termux, there are such errors as use of undeclared identifier.. my CC compiler and its dependent components are the latest version, but there are still problems. The reason is unknown. It indicates that the method is not declared at compile time. It is estimated that the CPU is weak and the compile execution order is related. It is just a guess.

Use the following solution directly:

apt install redis

That’s it. The bin executor is placed in usr/bin by default, and the configuration file is in usr/etc.

The local program cannot access the test environment redis cluster through public IP_ compromise

First, scene description

1. Test environment installation redis6, cluster deployment, three master and three slave. That is to achieve high concurrency, high availability, high security.

2. Redis creates clusters through bind intranet IP.

3. The local and test environment are not in the same LAN, and there is no VPN, so it is impossible to access redis through the test intranet IP.

4. Note: through the redis client, using the public IP + port, you can access redis.

Problem: spring program can’t access redis correctly through IP + port of public network.

Reason: when spring accesses the redis cluster, it first obtains the intranet IP and ports of all nodes in the redis cluster through the configured public IP and ports, and then the program finally accesses redis through the intranet IP and ports.

Second, the solution

1. Install the redis singleton on the test server.

2. Configuration file redis.conf Set daemonize to yes, that is to realize the background startup of redis.

3. In the test environment network security group, add the white list of local environment public IP, open port 6379.

4. Modify the local configuration file in spring program to access redis configuration mode. In this way, all technicians can connect to the test environment redis locally, and each technology does not need to open the redis service locally.

spring:
  redis:
    host: 47.112.108.1
    port: 6379
    timeout: 5000ms
  pool:
    max-active: 8
    min-idle: 0
    max-idle: 8
    max-wait: -1

 

Cache penetration, cache breakdown and cache avalanche solutions

1. Preface

Cache is used in program design. The front-end sends data access request to the background

case 1: first, the data is retrieved from the cache and returned to the front end directly

case 2: if the data is not retrieved from the cache, the data will be retrieved from the database. After the data is retrieved, the cache will be updated first and then returned to the front end

case 3: if it is not found in the database, it will be returned to null directly.

2.Cache penetration [penetration cache, database, no data]

definition: cache penetration refers to the fact that there is no data in the cache and database, but the user constantly initiates requests, such as data with ID of “- 1” or data with ID of extra large and nonexistent. At this time, the user is likely to be an attacker, and the attack will lead to excessive pressure on the database.

solutions:

1) The verification is added in the interface layer. For example: ① user authentication verification, ② ID basic verification, ID & lt; = 0 direct interception and return.

2) Use temporary caching mechanism. If neither the cache nor the database can be retrieved, the key value pair can be written as key null, and a shorter cache validity time can be set (for example, 30 seconds. If the cache validity time is set too long, it may lead to the failure of normal use). In this way, users can be prevented from repeatedly using the same ID to brute force query attacks.

3.Cache breakdown [breakdown cache, can be found in database]

definition: cache breakdown refers to the fact that there is no data in the cache and there is data in the database (generally, the cache time is expired). At this time, because there are too many concurrent users, they can not read the data in the cache at the same time, and they go to the database to get the data at the same time, resulting in an instant increase in the pressure on the database.

solutions:

1) Hotspot data is set to never expire.

2) Add mutex lock to synchronize query operation. The reference code is as follows.

static Lock reenLock = new ReentrantLock();
   public List<String> getData() throws InterruptedException {
       List<String> result = new ArrayList<String>();
     
       // Fetching from the cache
       result = getDataFromCache();

       if (result.isEmpty()) {
           if (reenLock.tryLock()) {
               try {
                   System.out.println("Get the lock, fetch the database from the DB and write it to the cache");
                   // fetch data from database
                   result = getDataFromDB();

                   // Write the query data to the cache
                   setDataToCache(result);

               } finally {
                   reenLock.unlock();// Release the lock
               }

           } else {
               result = getDataFromCache();// check the cache again first
               
               if (result.isEmpty()) {
                   System.out.println("No lock, no data in cache, waiting...") ;
                   Thread.sleep(100);//wait
                   return getData();//retry
               }

           }
       }

       return result;

   }

Note:

1) If there is data in the cache, the result will be returned directly.

2) If there is no data in the cache, get the lock and get the data from the database. Before releasing the lock, other parallel threads will wait for 100ms, and then go to the cache again to get the data. In this way, we can prevent the database from repeatedly fetching data and updating data in the cache.

3) Of course, this is a simplified process. In theory, it would be better if the lock could be added according to the key value. That is, thread a’s fetching key1 data from the database does not prevent thread B’s fetching key2 data. The above code obviously can’t do this. scheme: lock can be fine-grained to key.

4、 Cache avalanche

definition: cache avalanche refers to the phenomenon that a large amount of data in the cache is due to the expiration time, and the amount of query data is huge, which leads to too much pressure on the database and even down the machine.

different from “cache breakdown”: cache breakdown refers to the concurrent query of the same data; cache avalanche refers to the fact that different data have basically expired at the same time, and many data cannot be found in the cache, so they turn to query the database.

solutions:

1) When saving data to redis in batches, the failure time of each key is set to a random value, so as to ensure that the data will not fail in a large area at the same time.

setRedis(Key,value,time + Math.random () * 10000);

2) If redis is a cluster deployment, the hotspot data can be evenly distributed in different redis databases to avoid the problem of all failure.

3) Hotspot data settings will never expire. If there is an update operation, the cache can be updated.

Successful cases of redis distributed lock

1. Custom distributed lock tool class

package com.cache.redis.demo.util;

import org.apache.commons.lang.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.types.Expiration;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * redisImplementing distributed locks
 * */
public class RedisLockHelper {

    private static final Logger log = LoggerFactory.getLogger(RedisLockHelper.class);

    /**
     * Default interval for lock acquisition by rotation, in milliseconds
     */
    private static final int DEFAULT_ACQUIRE_RESOLUTION_MILLIS = 100;

    private static final String UNLOCK_LUA;

    static {
        StringBuilder sb = new StringBuilder();
        sb.append("if redis.call(\"get\",KEYS[1]) == ARGV[1] ");
        sb.append("then ");
        sb.append("    return redis.call(\"del\",KEYS[1]) ");
        sb.append("else ");
        sb.append("    return 0 ");
        sb.append("end ");
        UNLOCK_LUA = sb.toString();
    }

    private RedisTemplate redisTemplate;

    private final ThreadLocal<Map<String, LockVO&>&> lockMap = new ThreadLocal<&>();

    public RedisLockHelper(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * Get the lock and wait if it is not acquired
     *
     * @param key redis key
     * @param expire lock expiration time, in seconds
     */
    public void lock(final String key, long expire) {
        try {
            acquireLock(key, expire, -1);
        } catch (Exception e) {
            throw new RuntimeException("acquire lock exception", e);
        }
    }

    /**
     * If the lock is not acquired within the specified time, false is returned. otherwise, true is returned.
     *
     * @param key redis key
     * @param expire lock expiration time, in seconds
     * @param acquireTimeout The lock timeout period, -1 means never, in seconds.
     */
    public boolean lock(final String key, long expire, long acquireTimeout) throws RuntimeException {
        try {
            return acquireLock(key, expire, acquireTimeout);
        } catch (Exception e) {
            throw new RuntimeException("acquire lock exception", e);
        }
    }

    /**
     * 
     *
     * @param key redis key
     */
    public void unlock(String key) {
        try {
            release(key);
        } catch (Exception e) {
            throw new RuntimeException("release lock exception", e);
        }
    }


    private boolean acquireLock(String key, long expire, long acquireTimeout) throws InterruptedException {
        //If it was previously fetched and did not time out, then return the fetch success
        boolean acquired = acquired(key);
        if (acquired) {
            return true;
        }

        long acquireTime = acquireTimeout == -1 ?-1 : acquireTimeout * 1000 + System.currentTimeMillis();
        String currentTimeStr = DateFormatUtils.format(System.currentTimeMillis(),"yyyy-MM-dd HH:mm:ss.SSS");
        String acquireTimeStr = DateFormatUtils.format(acquireTime,"yyyy-MM-dd HH:mm:ss.SSS");
        log.info("Current time: {}, Timeout time.{}",currentTimeStr,acquireTimeStr);


        //The same process, for the same key lock, only allows the first one to try to get it.
        synchronized (key.intern()) {
            String lockId = UUID.randomUUID().toString();
            do {
                long before = System.currentTimeMillis();

                boolean hasLock = tryLock(key, expire, lockId);

                //Acquire lock successfully
                if (hasLock) {
                    long after = System.currentTimeMillis();
                    Map<String, LockVO&> map = lockMap.get();
                    if (map == null) {
                        map = new HashMap<&>(2);
                        lockMap.set(map);
                    }
                    map.put(key, new LockVO(1, lockId, expire * 1000 + before, expire * 1000 + after));
                    log.debug("acquire lock {} {} ", key, 1);
                    return true;
                }

                Thread.sleep(DEFAULT_ACQUIRE_RESOLUTION_MILLIS);

            } while (acquireTime == -1 || acquireTime &> System.currentTimeMillis());
        }
        log.debug("acquire lock {} fail,because timeout ", key);
        return false;
    }

    private boolean acquired(String key) {
        Map<String, LockVO&> map = lockMap.get();
        if (map == null || map.size() == 0 || !map.containsKey(key)) {
            return false;
        }

        LockVO vo = map.get(key);

        if (vo.beforeExpireTime < System.currentTimeMillis()) {
            log.debug("lock {} maybe release, because timeout ", key);
            return false;
        }
        int after = ++vo.count;
        log.debug("acquire lock {} {} ", key, after);
        return true;
    }

    private void release(String key) {
        Map<String, LockVO&> map = lockMap.get();
        if (map == null || map.size() == 0 || !map.containsKey(key)) {
            return;
        }

        LockVO vo = map.get(key);

        if (vo.afterExpireTime < System.currentTimeMillis()) {
            log.debug("release lock {}, because timeout ", key);
            map.remove(key);
            return;
        }
        int after = --vo.count;
        log.debug("release lock {} {} ", key, after);

        if (after &> 0) {
            return;
        }

        map.remove(key);
        RedisCallback<Boolean&> callback = (connection) -&>
                connection.eval(UNLOCK_LUA.getBytes(StandardCharsets.UTF_8), ReturnType.BOOLEAN, 1,
                        (RedisPrefix.LOCK_REDIS_PREFIX + key).getBytes(StandardCharsets.UTF_8), vo.value.getBytes(StandardCharsets.UTF_8));
        redisTemplate.execute(callback);
    }


    private boolean tryLock(String key, long expire, String lockId) {
        RedisCallback<Boolean&> callback = (connection) -&>
                connection.set((RedisPrefix.LOCK_REDIS_PREFIX + key).getBytes(StandardCharsets.UTF_8),
                        lockId.getBytes(StandardCharsets.UTF_8), Expiration.seconds(expire), RedisStringCommands.SetOption.SET_IF_ABSENT);
        return (Boolean) redisTemplate.execute(callback);
    }

    private static class LockVO {
        private int count;
        private String value;
        private long beforeExpireTime;
        private long afterExpireTime;

        LockVO(int count, String value, long beforeExpireTime, long afterExpireTime) {
            this.count = count;
            this.value = value;
            this.beforeExpireTime = beforeExpireTime;
            this.afterExpireTime = afterExpireTime;
        }
    }

}

2. Business thread

package com.cache.redis.demo.service;

import com.cache.redis.demo.util.RedisLockHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;

@Slf4j
public class MyThread implements Runnable {
    public static Integer count = 0;

    private String threadName;
    private StringRedisTemplate stringRedisTemplate;

    public MyThread() {
    }

    public MyThread(String threadName, StringRedisTemplate stringRedisTemplate) {
        this.threadName = threadName;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public void run() {
        String key = "sync-key";
        RedisLockHelper redisLockHelper = new RedisLockHelper(stringRedisTemplate);
        //Way 1: Do not set the lock timeout time, the lock expires in 2 seconds
        redisLockHelper.lock(key, 2L);

        // mode 2: no lock timeout of 5 seconds and lock expiration of 2 seconds
       /* Boolean flag = redisLockHelper.lock(key, 2L,5L);
        log.info("Obtain synchronization lock identification.{}",flag);
        if(false == flag){
            return;
        }*/

        count++;
        log.info("Action" + this.threadName + "output:" + count);

        redisLockHelper.unlock(key);
    }
}

3. Testing

package com.cache.redis.demo.util;

import com.cache.redis.demo.service.MyThread;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestLock {

    public static void main(String[] args) {
        StringRedisTemplate stringRedisTemplate = getRedisTemplate();
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);

        for (int i = 0; i < 100; i++) {
            MyThread myThread = new MyThread("threadName" + i, stringRedisTemplate);
            fixedThreadPool.execute(myThread);
        }

    }

    public static StringRedisTemplate getRedisTemplate() {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
        config.setHostName("127.0.0.1");
        config.setPort(6379);
        config.setPassword("pp@123e");
        JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(config);
       /* JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory();
        jedisConnectionFactory.setHostName("127.0.0.1");
        jedisConnectionFactory.setPort(6379);
        jedisConnectionFactory.setPassword("pp@123e");*/

        StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();
        Jackson2JsonRedisSerializer<Object&> fastJsonRedisSerializer = new Jackson2JsonRedisSerializer<Object&>(Object.class);
        //value fastJsonRedisSerializer
        stringRedisTemplate.setValueSerializer(fastJsonRedisSerializer);
        stringRedisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        //key StringRedisSerializer
        stringRedisTemplate.setKeySerializer(new StringRedisSerializer());
        stringRedisTemplate.setHashKeySerializer(new StringRedisSerializer());

        stringRedisTemplate.setConnectionFactory(jedisConnectionFactory);

        stringRedisTemplate.afterPropertiesSet();

        return stringRedisTemplate;
    }
}

Error creating bean with name ‘enablererediskeyspacenotificationsinitializer’

After the server is shut down, restart it, and start the web application log on it to print an error. Error creating bean with name ‘enablererediskeyspacenotificationsinitializer’ searches the Internet and finds that many of the answers are caused by the redis annotation related to springboot, and it is necessary to set redis.

But the problem is that this is not springboot, and there is no redis setting, because it was good before. After a long time, none of the reliable people suddenly thought about whether the problem lies in redis. Let’s take a look at the process of redis first,

ps -ef | grep Redis

Sure enough, redis didn’t start at all. First, open the redis service and see if it will change and if the error will change

Find the redis location
Find – name redis cli
(if redis or other services start, you can find the process number such as 12345, ll/proc/12345/CWD through PS – EF | grep XXXX to find the corresponding service location. )

Start the redis service
to the corresponding path to start the service
redis server /Redis conf
(note that the paths of redis server and redis conf are at the same level or not. )

Service start, web application process kill and restart, no error. So the reason for this error is related to whether the redis service is started or not.