Non-self-energizing ID field, to avoid generating a unique ID (pdfNo to Example No.) RedisLock / ReadLock

Non-self-energizing ID field, to avoid generating a unique ID (pdfNo to Example No.)

There is a scene, the user query delays flight information, and then produce a number, the default first number is 1000001, followed by the new number from default by one. Every time someone comes to check delay information, if the delay information exists, then take the field pdfNo query the database, query the largest number, and then later +1, then insert a new record delays. This will result in more than the same query, and generate a delayed record, pdfNo the number is duplication.

After analysis, the Men leader said there are more than two kinds of solutions, one is distributed lock options, one is to insert into select from, one in RedisLock program.

I am stupid, that under the insert into select from, and RedisLock program

insert into select from:

When warehousing Queries under maximum pdfNo, then add a storage

方法一:
INSERT INTO Websites (name, country)
SELECT app_name, country FROM apps
WHERE id=1;

  

II: 
table structure as FIG 
insert into test_aaa (title, pdfno) select "hello", max (pdfno) +1 as pdfmax from test_aaa;

  

 

RedisLock 方法

VariableKeyLock.java
import java.util.concurrent.locks.Lock;

/**
 * 可变key锁
 *
 * @author zhangyang-b
 */
public interface VariableKeyLock extends Lock {

    boolean tryLock(String key);

    void lock(String key);

    void unlock(String key);
}

  

RedisLock.java

public class RedisLock implements VariableKeyLock {

    public static final String LOCK = "LOCK";

    @Autowired
    private RedisConnectionFactory factory;

    private ThreadLocal<String> localValue = new ThreadLocal<String>();

    /**
     * 解锁lua脚本
     */
    private static final String UNLOCK_LUA =
        "if redis.call(\"get\",KEYS[1]) == ARGV[1] then return redis.call(\"del\",KEYS[1]) else return 0 end";

    @Override
    public void lock() {
        if (!tryLock()) {
            try {
                Thread.sleep(new Random().nextInt(10) + 1);
            } catch (InterruptedException e) {
                log.error(e.getMessage(), e);
            }
            lock();
        }
    }

    @Override
    public void lock(String key) {
        if (!tryLock(key)) {
            try {
                Thread.sleep(new Random().nextInt(10) + 1);
            } catch (InterruptedException e) {
                log.error(e.getMessage(), e);
            }
            lock(key);
        }
    }

    @Override
    public boolean tryLock() {
        RedisConnection connection = null;
        try {
            connection = factory.getConnection();
            Jedis jedis = (Jedis)connection.getNativeConnection();
            String value = UUID.randomUUID().toString();
            localValue.set(value);
            String ret = jedis.set(LOCK, value, "NX", "PX", 10000);
            return ret != null && "OK".equals(ret);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
        return false;
    }

    @Override
    public boolean tryLock(String key) {
        RedisConnection connection = null;
        try {
            connection = factory.getConnection();
            Jedis jedis = (Jedis)connection.getNativeConnection();
            String value = UUID.randomUUID().toString();
            localValue.set(value);
            String ret = jedis.set(key, value, "NX", "PX", 10000);
            return ret != null && "OK".equals(ret);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
        return false;
    }

    @Override
    public void unlock() {
        String script = UNLOCK_LUA;
        RedisConnection connection = null;
        try {
            connection = factory.getConnection();
            Object jedis = connection.getNativeConnection();
            if (jedis instanceof Jedis) {
                ((Jedis)jedis).eval(script, Arrays.asList(LOCK), Arrays.asList(localValue.get()));
            } else if (jedis instanceof JedisCluster) {
                ((JedisCluster)jedis).eval(script, Arrays.asList(LOCK), Arrays.asList(localValue.get()));
            }

        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (connection != null) {
                connection.close();
            }
        }

    }

    @Override
    public void unlock(String key) {
        String script = UNLOCK_LUA;
        RedisConnection connection = null;
        try {
            connection = factory.getConnection();
            Object jedis = connection.getNativeConnection();
            if (jedis instanceof Jedis) {
                ((Jedis)jedis).eval(script, Arrays.asList(key), Arrays.asList(localValue.get()));
            } else if (jedis instanceof JedisCluster) {
                ((JedisCluster)jedis).eval(script, Arrays.asList(key), Arrays.asList(localValue.get()));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (connection != null) {
                connection.close();
            }
        }
    }

}

  

 

usage:
      redisLock.lock(key名);
        try{
            int maxPdfNo = 0;
            try{
                maxPdfNo = flightDelayPdfJService.queryMaxPdfNo();
            }catch (Exception e){
                e.printStackTrace();
            }
            if(maxPdfNo > 0){
                return maxPdfNo + 1;
            }else{
                return 1000001;
            }
        }finally {
            redisLock.unlock(key名);
        }

  








 

Guess you like

Origin www.cnblogs.com/achengmu/p/10973931.html