05Redis -- transaction, optimistic lock, Jedis

Posted by serg4444 on Sat, 05 Mar 2022 01:35:00 +0100

catalogue

Normal execution of transactions

Abandon transaction

Compiled exception

Runtime exception (I/O)

Monitor} Watch (frequently asked in interview)

redis monitoring test

Normal execution succeeded!  

Test multithreading to modify the value. Using watch can be used as redis optimistic lock operation

Jedis

Test:

1. Import corresponding dependencies

2. Coding test:

Redis -Key

Redis -String

 Redis-List

affair

The transaction executed successfully

Exception in transaction

redis transaction essence: a set of commands! All commands in a transaction are serialized and executed in sequence during execution
One time, sequential, exclusive, execute some columns of commands

A single redis command maintains atomicity, but transactions do not guarantee atomicity
redis transactions do not have the concept of isolation level

All commands are not executed directly in the transaction. Only the initiated execution command can be executed! Exec

redis transaction

  • Open transaction (multi)
  • Order to join the team
  • Execute transaction (exec)

Normal execution of transactions

127.0.0.1:6379> multi            # Will open is a transaction
OK
# Order to join the team
127.0.0.1:6379(TX)> set k1 v1
QUEUED                           # QUEUED queue 
127.0.0.1:6379(TX)> set k2 v2 
QUEUED
127.0.0.1:6379(TX)> get k1
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> exec        # implement
1) OK
2) OK
3) "v1"
4) OK

Abandon transaction

127.0.0.1:6379> multi          # Open transaction
OK
127.0.0.1:6379(TX)> set k1 v1 
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> DISCARD  # Cancel transaction
OK
127.0.0.1:6379> get k3       # None of the commands in the transaction queue will be executed 
(nil)

Compiled exception

There is a problem with the code and the command. All commands in the transaction will not be executed

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 v1
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> setget k4 v4  # Wrong command
(error) ERR unknown command `setget`, with args beginning with: `k4`, `v4`, 
127.0.0.1:6379(TX)> set k5 v5
QUEUED
127.0.0.1:6379(TX)> exec          # Error in executing transaction  
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get k5            # All commands will not be executed
(nil)

Runtime exception (I/O)

(other commands are executed normally, and the error command throws an exception)

127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> incr k1    # When an error occurs during execution, incr can only be self incremented. The number type cannot be String type
QUEUED
127.0.0.1:6379(TX)> set k2 v2
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> get k3 
QUEUED
127.0.0.1:6379(TX)> exec
1) (error) ERR value is not an integer or out of range # Although the first command reported an error, it was still executed normally and successfully
2) OK
3) OK
4) "v3"
127.0.0.1:6379> get k2
"v2"
127.0.0.1:6379> get k3
"v3"

Monitor} Watch (frequently asked in interview)

Pessimistic lock: very pessimistic, thinking that problems will occur at any time, lock everything, and reduce efficiency
Optimistic lock:

  • I'm optimistic that there will be no problem at any time, so I don't lock it. When updating the data, I will judge whether someone has changed the data during this period. version!
  • Get version
  • Compare version when updating

redis monitoring test

Normal execution succeeded!  

127.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set out 0
OK
127.0.0.1:6379> watch money            # Monitor money objects
OK
127.0.0.1:6379> multi        # The transaction ends normally and there is no change in the data period. At this time, the normal execution is successful
OK
127.0.0.1:6379(TX)> DECRBY money 20 
QUEUED
127.0.0.1:6379(TX)> INCRBY out 20
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20

Test multithreading to modify the value. Using watch can be used as redis optimistic lock operation

Thread one

127.0.0.1:6379> watch money  # Monitor money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 10 
QUEUED
127.0.0.1:6379(TX)> incrby out 10
QUEUED
127.0.0.1:6379(TX)> exec # Before execution, another thread modifies our value. At this time, it will
(nil)                      Cause transaction execution failure  

Thread two

127.0.0.1:6379> get money
"80"
127.0.0.1:6379> set money 1000
OK

At this point, the thread wants to continue the operation

127.0.0.1:6379(TX)> exec
(nil)
127.0.0.1:6379> unwatch         # 1. If the transaction fails to execute, unlock it first
OK
127.0.0.1:6379> watch money     # 2. Get the latest value, which is similar to MySql select version in this monitoring   
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 10
QUEUED
127.0.0.1:6379(TX)> incrby money 10
QUEUED
127.0.0.1:6379(TX)> exec        # Compare whether the monitored value has changed. If there is no change, it can be executed successfully
1) (integer) 990                  If there is a change, the execution fails  
2) (integer) 1000

Jedis

We should use java to operate redis. We should know its nature and why

Jedis is an officially recommended Java connection development tool, which uses Java to operate redis middleware. If you want to use java to operate redis, you must be very familiar with jedis

Test:

1. Import corresponding dependencies

        <!--Import jedis My bag-->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>3.2.0</version>
        </dependency>
        <!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.70</version>
        </dependency>

2. Coding test:

  • Link redis
  • Operation command
  • break link
Open port 6379
firewall-cmd --permanent --zone=public --add-port=6379/tcp --permanent

Restart firewall service
systemctl restart firewalld.service

restart redis-server
redis-server gconfig/redis.conf 
public class RedisTest {
    public static void main(String[] args) {

        //1. New jedis object
        Jedis jedis = new Jedis("127.0.0.1",6379);
        //All the commands of Jedis are all the commands we learned before
        System.out.println(jedis.ping());
    }
}

Output:

 

Redis -Key

/**
 * @author gh  Email:@2495140780qq.com
 * @Description
 * @date 2022-03-04-11:54 am
 */
public class TestKey {
    public static void main(String[] args) {

        Jedis jedis = new Jedis("127.0.0.1",6379);
        System.out.println("Clear the data in the specified database:" + jedis.flushDB());
        System.out.println("Clear all data:" + jedis.flushAll());
        System.out.println("newly added<'username','zhangsan'>Key value pairs:" + jedis.set("username","zhangsan"));
        System.out.println("newly added<'password','123456'>Key value pairs:" + jedis.set("password","123456"));
        System.out.print("All keys in the system are as follows:");
        Set<String> keys = jedis.keys("*");
        System.out.println(keys);
        System.out.println("Delete key password: " + jedis.del("password"));
        System.out.println("Judgment key password Is there:" + jedis.exists("password"));
        System.out.println("View key username The type of value stored" + jedis.type("username"));
        System.out.println("Random return key A of space" + jedis.randomKey());
        System.out.println("rename key: " + jedis.rename("username","userName"));
        System.out.println("Take out the modified userName: " + jedis.get("userName"));
        System.out.println("Query by index:" + jedis.select(0));
        System.out.println("Return to the current database key Quantity of:" + jedis.dbSize());
        System.out.println("Delete all in the currently selected database key: " + jedis.flushDB());
        System.out.println("Return to the current database key Quantity of:" + jedis.dbSize());
        System.out.println("Delete all that in all databases key: " + jedis.flushAll());
    }
}

Redis -String

/**
 * @author gh  Email:@2495140780qq.com
 * @Description
 * @date 2022-03-04-12:06 PM
 */
public class TestString {
    public static void main(String[] args) {

        Jedis jedis = new Jedis("127.0.0.1", 6379);

        jedis.flushDB();
        System.out.println(" ===========Add data ===========");
        System.out.println(jedis.set("key1", "value1"));
        System.out.println(jedis.set("key2", "value2"));
        System.out.println(jedis.set("key3", "value3"));
        System.out.println("Delete key key2:" + jedis.del("key2"));
        System.out.println("Get key key2:" + jedis.get("key2"));
        System.out.println("modify key1:" + jedis.set("key1", "value1Changed"));
        System.out.println("obtain key1 Value of:" + jedis.get("key1"));
        System.out.println("stay key3 Add value after:" + jedis.append("key3", "End"));
        System.out.println("key3 Value of:" + jedis.get("key3"));

        System.out.println("Add multiple key value pairs:" + jedis.mset("key01", "value01", "key02", "value02", "key03", "values03"));
        System.out.println("Get multiple key value pairs:" + jedis.mget("key01", "key02", "key03"));
        System.out.println("Get multiple key value pairs:" + jedis.mget("key01", "key02", "key03", "key04"));
        System.out.println(" Delete multiple key value pairs:" + jedis.del("key01", " key02"));
        System.out.println(" Get multiple key value pairs:" + jedis.mget("key01", "key02", "key03"));

        jedis.flushDB();
        System.out.println("===========Adding a key value pair prevents overwriting the original value==========");
        System.out.println(jedis.setnx("key1", "value1"));
        System.out.println(jedis.setnx("key2", "value2"));
        System.out.println(jedis.setnx("key2", "value2-new"));
        System.out.println(jedis.get("key1"));
        System.out.println(jedis.get("key2"));

        System.out.println("===========Add key value pairs and set effective time=============");
        System.out.println(jedis.setex("key3", 2, "value3"));
        System.out.println(jedis.get("key3"));
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println(jedis.get("key3"));
            System.out.println("===========Get the original value and update it to the new value==========");
            System.out.println(jedis.getSet("key2", "key2GetSet"));
            System.out.println(jedis.get("kev2"));
            System.out.println("get key2 String of values:" + jedis.getrange("key2", 2, 4));
        }
    }
}

 

 Redis-List

/**
 * @author gh  Email:@2495140780qq.com
 * @Description
 * @date 2022-03-04-12:28 PM
 */
public class TestList {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1", 6379);

        jedis.flushDB();

        System.out.println("=========Add a list========");
        jedis.lpush("collections", "ArrayList", "Vector", "Stack", "HashMap", "WeakHashMap", "LinkedHashmap");
        jedis.lpush("collections", "Hashset");
        jedis.lpush("collections", "TreeSet");
        jedis.lpush("collections", "TreeMap");
        System.out.println("collections Content of : "+jedis.lrange("collections", 0 , -1));
        System.out.println("collections Interval 0 -3 Content of : "+jedis.lrange("collections", 0 , 3));

        System.out.println("======================");
        //Delete the value specified in the list. The second parameter is the number of deleted values (when there are duplicates). The value add ed later is deleted first, which is similar to out of the stack
        System.out.println("Deletes the specified element:" + jedis.lrem("collections",2,"HashMap"));
        System.out.println("collections Content of : "+jedis.lrange("collections", 0 , -1));
        System.out.println("collections Interval 0 -3 Content of : "+jedis.lrange("collections", 0 , 3));
        System.out.println("collections List out of stack (left end) : "+jedis.lpop("collections"));
        System.out.println("collections Content of : "+jedis.lrange("collections", 0 , -1));
        System.out.println("collections Add elements, from the right end of the list rpush : "+jedis.rpush("collections", "EnumMap"));
        System.out.println("collections Content of : "+jedis.lrange("collections", 0 , -1));
        System.out.println("collections List out of stack (right end) : "+jedis.rpop("collections"));
        System.out.println("collections Content of : "+jedis.lrange("collections", 0 , -1));
        System.out.println("modify collections Specifies the contents of subscript 1:" + jedis.lset("collections",1,"LinkArrayList"));
        System.out.println("collections Content of : "+jedis.lrange("collections", 0 , -1));

        System.out.println("=============================");
        System.out.println("collections Length of : "+jedis.llen("collections"));
        System.out.println("obtain collections Specifies the contents of subscript 2:" + jedis.lindex("collections",2));

        System.out.println("=============================");
        jedis.lpush("sortedList", "3", "6", "2", "0", "7", "4");
        System.out.println("sortedList Before sorting" + jedis.lrange("sortedList",0,-1));
        System.out.println(jedis.sort("sortedList"));
        System.out.println("sortedList After sorting" + jedis.lrange("sortedList",0,-1));
    }
}

 

affair

The transaction executed successfully

/**
 * @author gh  Email:@2495140780qq.com
 * @Description
 * @date 2022-03-04-2:30 PM
 */
public class TestTx {
    public static void main(String[] args) {

        Jedis jedis = new Jedis("127.0.0.1",6379);
        jedis.flushDB();

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "zhangsan");
        jsonObject.put("age", 15);

        String result = jsonObject.toString();

        Transaction multi = jedis.multi();//Open transaction
        try {
            multi.set("user1", result);
            multi.set("user2", result);

            multi.exec();//Execute transaction
        } catch (Exception e) {
            //If an exception occurs, the transaction is abandoned
            multi.discard();
            e.printStackTrace();
        } finally {
            System.out.println(jedis.get("user1"));
            System.out.println(jedis.get("user2"));
            jedis.close();//Close link
        }
    }
}

 

Exception in transaction

/**
 * @author gh  Email:@2495140780qq.com
 * @Description
 * @date 2022-03-04-2:30 PM
 */
public class TestTx {
    public static void main(String[] args) {

        Jedis jedis = new Jedis("127.0.0.1",6379);
        jedis.flushDB();

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("name", "zhangsan");
        jsonObject.put("age", 15);

        String result = jsonObject.toString();

        Transaction multi = jedis.multi();//Open transaction
        try {
            multi.set("user1", result);
            multi.set("user2", result);

            int i = 1 / 0;  //Manufacturing exception
            
            multi.exec();//Execute transaction
        } catch (Exception e) {
            //If an exception occurs, the transaction is abandoned
            multi.discard();
            e.printStackTrace();
        } finally {
            System.out.println(jedis.get("user1"));
            System.out.println(jedis.get("user2"));
            jedis.close();//Close link
        }
    }
}

Topics: Database Redis nosql