Redis advanced project practice, complete collection of old boy linux e-books

Function [#](

)

Ensure complete data transmission

Redis distributed lock implementation source code explanation [#](

)

Graphic explanation [#](

)

Step [#](

)

  1. Distributed locks meet two conditions: one is the lock with effective time, and the other is high-performance unlocking
  2. redis commands setnx (set if not exist) and setex (set expire value) are used
  3. The unlocking process cannot be omitted, otherwise the task will never expire when it is executed once
  4. Put the locking code and task logic into the try catch code block, and the unlocking process into the finally code block

Project structure [#](

)

pom.xml[#](

)

<?xml version="1.0" encoding="UTF-8"?>    4.0.0    org.springframework.boot  spring-boot-starter-parent  2.3.3.RELEASE    
     com.cyb  yb-mobile-redis  0.0.1-SNAPSHOT  yb-mobile-redis  Demo project for Spring Boot    

application.properties[#](

)

spring.redis.database=0 spring.redis.host=192.168.199.142 spring.redis.port=6379 spring.redis.password=12345678 server.port=9001

RedisService.java[#](

)

package com.cyb.ybmobileredis.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.*; import org.springframework.stereotype.Service; import java.io.Serializable; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; /** * @ClassName: RedisService
 * @Description: TODO
 * @Author: chenyb
 * @Date: 2020/8/16 5:39 afternoon
 * @Versiion: 1.0 */ @Service public  class RedisService  {  @Autowired private RedisTemplate redisTemplate; private  static  double size =  Math.pow(2,  32); /** * Write cache
     *
     * @param key
     * @param offset   Bit 8Bit=1Byte
     * @return  */  public  boolean setBit(String key,  long offset,  boolean isShow)  { boolean result =  false; try {  ValueOperations

LockNxExJob.java[#](

)

package com.cyb.ybmobileredis.schedule; import com.cyb.ybmobileredis.service.RedisService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Enumeration; /** * @ClassName: LockNxExJob
 * @Description: Distributed lock acquisition and release
 * @Author: chenyb
 * @Date: 2020/8/16 5:44 afternoon
 * @Versiion: 1.0 */ @Service public  class LockNxExJob  { private  static  final  Logger logger =  LoggerFactory.getLogger(LockNxExJob.class);  @Autowired private RedisService redisService;  @Autowired private RedisTemplate redisTemplate; private  static  String LOCK_PREFIX =  "prefix_";  @Scheduled(fixedRate =  8000) public  void lockJob()  {  String  lock = LOCK_PREFIX +  "LockNxExJob"; boolean nxRet=false; try{ //redistemplate setnx operation nxret = redistemplate opsForValue(). setIfAbsent(lock,getHostIp());   Object lockValue = redisService. get(lock);   System. out. println(lockValue); // Failed to obtain lock if (! Nxret) {string value = (string) redisservice.get (lock); / / print the server IP logger.info (system. Currenttimemillis() + "get lock fail, lock long to: {}", value) currently occupying the lock; return;  } Else {redistemplate. Opsforvalue(). Set (lock, gethostip(), 3600); / / successful lock acquisition logger.info (system. Currenttimemillis() + "start lock locknxexjob success"); thread.sleep (4000);}} catch (Exception e){ logger.error("lock error",e);  } Finally {if (nxret) {system.out.println ("lock released successfully"); redisService.remove(lock);}}} / * ** Method for obtaining local intranet IP address
     * @return  */  private  static String getHostIp(){ try{  Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces(); while (allNetInterfaces.hasMoreElements()){  NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();  Enumeration addresses = netInterface.getInetAddresses(); while (addresses.hasMoreElements()){  InetAddress ip = (InetAddress) addresses.nextElement(); if  (ip !=  null  && ip instanceof Inet4Address &&  !ip.isLoopbackAddress()  //Loopback address is the local address. The loopback range of IPv4 is 127.0 0.0 ~ 127.255. 255.255  && ip. getHostAddress(). indexOf(":")==-1){ return ip.getHostAddress();  }  }  }  } catch(Exception e){ e.printStackTrace();  }  return  null;  }  }

Verify [#](

)

Run one jar on Linux, one locally, one successfully obtains the lock, and the other fails to obtain the lock

Possible problems with Redis distributed locks [#](

)

We have implemented the distributed lock function with code above. Only one lock can be successfully obtained at the same time. It can be seen from the above figure that in extreme cases, after the first Server successfully obtains the lock, the service or Redis goes down, which will lead to the problem that the Redis lock cannot be released, and other servers always fail to obtain the lock.

Simulate server acquisition lock downtime [#](

)

First run the project and obtain the lock, immediately kill -9 process id and kill the current process. Then, when running the project, the console will always prompt that obtaining the lock failed.

Solutions (key) [#](

)

  1. If you execute one command at a time, this will not happen. Use Lua script
  2. Since 2.6, Redis supports the combination of setnx and setex

lua script [#](

)

  1. Add a suffix to the redource directory lua ending file
  2. Writing lua scripts
  3. key and arg passed in lua script
  4. Call redistemplate The execute method executes the script

Writing lua scripts

local lockKey = KEYS[1]  local lockValue = KEYS[2] -- setnx info local result_1 = redis.call('SETNX',lockKey,lockValue) if result_1 ==  true then  local result_2 = redis.call('SETEX',lockKey,3600,lockValue) return result_1 else  return result_1 end

Encapsulate and call lua script methods

 @Autowired private RedisTemplate redisTemplate; private  DefaultRedisScript lockScript; /** * Get lua results
     *
     * @param key   key
     * @param value value
     * @return  */  public Boolean luaExpress(String key,  String value)  { lockScript =  new  DefaultRedisScript<>(); lockScript.setScriptSource( new  ResourceScriptSource(new  ClassPathResource("add.lua"))  ); //Set the return value lockscript setResultType(Boolean.class); // Encapsulation parameter list keylist = new ArrayList < > (); keyList. add(key);  keyList. add(value);   Boolean result = (Boolean) redisTemplate. execute(lockScript, keyList);  return result;  }

Distributed locking method before transformation

package com.cyb.ybmobileredis.schedule; import com.cyb.ybmobileredis.service.RedisService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scripting.support.ResourceScriptSource; import org.springframework.stereotype.Service; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; /** * @ClassName: LockNxExJob
 * @Description: Distributed lock acquisition and release
 * @Author: chenyb
 * @Date: 2020/8/16 5:44 afternoon
 * @Versiion: 1.0 */ @Service public  class LockNxExJob  { private  static  final  Logger logger =  LoggerFactory.getLogger(LockNxExJob.class);  @Autowired private RedisService redisService;  @Autowired private RedisTemplate redisTemplate; private  static  String LOCK_PREFIX =  "prefix_"; private  DefaultRedisScript lockScript; //General distributed lock / / @ scheduled (fixedrate = 8000) / / public void lockjob() {/ / string lock = lock_prefix + "locknxexjob"; / / Boolean nxret = false; / / try {/ / / / redistemplate setnx operation / / nxRet = redisTemplate.opsForValue().setIfAbsent(lock, getHostIp()); // Object lockValue = redisService.get(lock); // System.out.println(lockValue) ; //  // Failed to obtain the lock / / if (! Nxret) {/ / string value = (string) redisservice.get (lock); / / / print the server IP currently occupying the lock / / logger.info (system. Currenttimemillis() + "get lock fail, lock long to: {}", value)// return; // }  Else {/ / redistemplate. Opsforvalue(). Set (lock, gethostip(), 3600000); / / / / lock acquisition succeeds / / logger.info (system. Currenttimemillis() + "start lock locknxexjob success"); / / thread.sleep (4000); / /} catch (exception E) {/ / logger.error ("lock error", e); / /} finally {/ / if (nxret) {/ / system.out.println ("lock release success") ; //  redisService.remove(lock); // } // } // }  /** * lua script distributed lock * / @ scheduled (fixedrate = 8000) public void lualockjob() {string lock = lock_prefix + "locknxexjob"; Boolean nxret = false; try {/ / redistemplate setnx operation nxret = luaexpress (lock, gethostip()); object lockvalue = redisservice.get (lock); system.out.println (lockvalue); / / failed to obtain lock if (! Nxret) {string value = (string) redisservice.get (lock); / / print the server IP logger.info (system. Currenttimemillis() + "Lua get lock fail, lock long to: {}", value); return;  }  Else {redistemplate. Opsforvalue(). Set (lock, gethostip(), 3600000); / / successful lock acquisition logger.info (system. Currenttimemillis() + "Lua start lock locknxexjob success"); thread.sleep (4000);}} catch (Exception e)  { logger.error("lua lock error", e);  }  Finally {if (nxret) {system. Out. Println ("Lua successfully releases the lock"); redisService.remove(lock);}}} / * ** Get Lua results
     *
     * @param key   key
     * @param value value
     * @return  */  public Boolean luaExpress(String key,  String value)  { lockScript =  new  DefaultRedisScript<>(); lockScript.setScriptSource( new  ResourceScriptSource(new  ClassPathResource("add.lua"))  ); //Set the return value lockscript setResultType(Boolean.class); // Encapsulation parameter list keylist = new ArrayList < > (); keyList. add(key);  keyList. add(value);   Boolean result = (Boolean) redisTemplate. execute(lockScript, keyList);  return result;  } /** *  Method for obtaining local intranet IP address
     *
     * @return  */  private  static String getHostIp()  { try {  Enumeration allNetInterfaces = NetworkInterface.getNetworkInterfaces(); while (allNetInterfaces.hasMoreElements())  {  NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();  Enumeration addresses = netInterface.getInetAddresses(); while (addresses.hasMoreElements())  {  InetAddress ip = (InetAddress) addresses.nextElement(); if  (ip !=  null  && ip instanceof Inet4Address &&  !ip.isLoopbackAddress()  //Loopback address is the local address. The loopback range of IPv4 is 127.0 0.0 ~ 127.255. 255.255  && ip. getHostAddress(). indexOf(":")  ==  -1)  { return ip.getHostAddress();  }  }  }  }  catch (Exception e)  { e.printStackTrace();  }  return  null;  }  }

Verify [#](

)

Supplement and solve the key garbled problem in Redis [#](

)

Just add redisconfig Java configuration file

package com.cyb.ybmobileredis.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; /** * @ClassName: RedisConfig
 * @Description: Redis Configuration class
 * @Author: chenyb
 * @Date: 2020/8/16 11:48 afternoon
 * @Versiion: 1.0 */ @Configuration //The current class is the configuration class public class redisconfig {@ bean / / redistemplate, which is injected into the Spring container public redistemplate

RedisConnection implements distributed locks [#](

)

brief introduction

Redisconnection implements distributed locking. redisTemplate is used to operate redisconnection, and setnx and setex commands are used together

code implementation

package com.cyb.ybmobileredis.schedule; import com.cyb.ybmobileredis.service.RedisService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisStringCommands; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.types.Expiration; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scripting.support.ResourceScriptSource; import org.springframework.stereotype.Service; import java.net.Inet4Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; /** * @ClassName: LockNxExJob
 * @Description: Distributed lock acquisition and release
 * @Author: chenyb
 * @Date: 2020/8/16 5:44 afternoon
 * @Versiion: 1.0 */ @Service public  class LockNxExJob  { private  static  final  Logger logger =  LoggerFactory.getLogger(LockNxExJob.class);  @Autowired private RedisService redisService;  @Autowired private RedisTemplate redisTemplate; private  static  String LOCK_PREFIX =  "prefix_"; private  DefaultRedisScript lockScript; //General distributed lock / / @ scheduled (fixedrate = 8000) / / public void lockjob() {/ / string lock = lock_prefix + "locknxexjob"; / / Boolean nxret = false; / / try {/ / / / redistemplate setnx operation / / nxRet = redisTemplate.opsForValue().setIfAbsent(lock, getHostIp()); // Object lockValue = redisService.get(lock); // System.out.println(lockValue) ; //  // Failed to obtain the lock / / if (! Nxret) {/ / string value = (string) redisservice.get (lock); / / / print the server IP currently occupying the lock / / logger.info (system. Currenttimemillis() + "get lock fail, lock long to: {}", value)// return; // }  Else {/ / redistemplate. Opsforvalue(). Set (lock, gethostip(), 3600000); / / / / lock acquisition succeeds / / logger.info (system. Currenttimemillis() + "start lock locknxexjob success"); / / thread.sleep (4000); / /} catch (exception E) {/ / logger.error ("lock error", e); / /} finally {/ / if (nxret) {/ / system.out.println ("lock release success") ; //  redisService.remove(lock); // } // } // }  /** * lua script distributed lock * / / / @ scheduled (fixedrate = 8000) / / public void lualockjob() {/ / string lock = lock_prefix + "locknxexjob"; / / Boolean nxret = false; / / try {/ / / / redistemplate setnx operation / / / / nxRet = luaExpress(lock,getHostIp()); // nxRet = setLock(lock,600); // Object lockValue = redisService.get(lock); // System.out.println(lockValue); //  // Failed to obtain the lock / / if (! Nxret) {/ / string value = (string) redisservice.get (lock); / / / print the server IP currently occupying the lock / / logger.info (system. Currenttimemillis() + "Lua get lock fail, lock long to: {}", value)// return; // }  Else {/ / redistemplate. Opsforvalue(). Set (lock, gethostip(), 3600000); / / / / lock acquisition succeeds / / logger.info (system. Currenttimemillis() + "Lua start lock locknxexjob success"); / / thread.sleep (4000); / /} catch (exception E) {/ / logger.error ("Lua lock error", e); / / /} finally {/ / if (nxret) {/ / system.out.println( "Lua release lock succeeded")// redisService.remove(lock); // } // } // }  /** * setnx and setex use distributed locks * / @ scheduled (fixedrate = 8000) public void setlockjob() {string lock = lock_prefix + "locknxexjob"; Boolean nxret = false; try {/ / redistemplate setnx operation / / nxret = luaexpress (lock, gethostip()); nxret = setlock (lock, gethostip()); object lockvalue = redisservice.get (lock); system.out.println (lockvalue) ; // Failed to obtain lock if (! Nxret) {string value = (string) redisservice.get (lock); / / print the server IP logger.info (system. Currenttimemillis() + "setnx and setex get lock fail, lock long to: {}", value) currently occupying the lock; return;  }  Else {redistemplate. Opsforvalue(). Set (lock, gethostip(), 3600000); / / successful lock acquisition logger.info (system. Currenttimemillis() + "setnx and setex start lock locknxexjob success"); thread.sleep (4000);}} catch (Exception e)  { logger.error(" setnx and setex lock error", e);  }  Finally {if (nxret) {system.out.println ("setnx and setex release lock successfully"); redisservice.remove (lock);}}} / * ** Setnx with setex
     * @param key key
     * @param value value
     * @param expire Timeout
     * @return  */  public  boolean setLock(String key,String value,long expire){ try{  Boolean result=(boolean)redisTemplate.execute(new  RedisCallback()  {  @Override public  Boolean doInRedis(RedisConnection connection)  throws DataAccessException  { return connection.set(key.getBytes(),value.getBytes(),Expiration.seconds(expire),RedisStringCommands.SetOption.ifAbsent());  }  }); return result;  }catch (Exception e){ logger.error("set redis occured an exception",e);  } return  false;  } /** * Get lua results
     *
     * @param key   key
     * @param value value
     * @return  */  public Boolean luaExpress(String key,  String value)  { lockScript =  new  DefaultRedisScript<>(); lockScript.setScriptSource( new  ResourceScriptSource(new  ClassPathResource("add.lua"))  ); //Set the return value lockscript setResultType(Boolean.class); // Encapsulation parameter list keylist = new ArrayList < > (); keyList. add(key);  keyList. add(value);   Boolean result = (Boolean) redisTemplate. execute(lockScript, keyList);  return result;  } /** *  Method for obtaining local intranet IP address


## last

## Authoritative guide - the first Docker book

Lead to completion Docker Installation, deployment, management and expansion of, so that it can go through the whole development life cycle from test to production Docker For what scenario. And this book Docker The learning authority guide introduces the basics of its components, and then uses Docker Building containers and services to accomplish various tasks: Leveraging Docker Set up a test environment for a new project to demonstrate how to use continuous integration workflow integration Docker,How to build application services and platforms, and how to use Docker of API,How to extend Docker. 

A total of: introduction, installation Docker,Docker Getting started and using Docker Image and warehouse, used in testing Docker,use Docker Build services, use Fig Orchestration  Docke,use Docker API,Get help and help Docker Improve the knowledge of 9 chapters.

![image](https://img-blog.csdnimg.cn/img_convert/dce53b293cbd6179fb9d8ef1390b9b35.png)

![image](https://img-blog.csdnimg.cn/img_convert/bf5edba58e1e6a2a3349810286ba29c0.png)

![image](https://img-blog.csdnimg.cn/img_convert/a87cc58b8e689a0c40eeeb7a692b8cba.png)

![image](https://img-blog.csdnimg.cn/img_convert/82ca41ac2cd8fcd7b1a3176c3c0f87df.png)

It is highly recommended by Ali“ K8S+Docker "Study guide" - in simple terms Kubernetes: theory+Actual combat, authoritative guide-First book Docker Book, after reading, two words describe, love, love!

**[CodeChina Open source project: [first tier big factory] Java Analysis of interview questions+Core summary learning notes+Latest explanation Video]](https://codechina.csdn.net/m0_60958482/java-p7)**

qTmsvI-1630390286675)]

[External chain picture transfer...(img-i8LUJVUE-1630390286675)]

It is highly recommended by Ali“ K8S+Docker "Study guide" - in simple terms Kubernetes: theory+Actual combat, authoritative guide-First book Docker Book, after reading, two words describe, love, love!

**[CodeChina Open source project: [first tier big factory] Java Analysis of interview questions+Core summary learning notes+Latest explanation Video]](https://codechina.csdn.net/m0_60958482/java-p7)**

Keywords: Java Linux Database Redis Back-end

Added by thoand on Sat, 18 Dec 2021 06:11:36 +0200