Reproduced in: http://www.itxuexiwang.com/a/shujukujishu/redis/2016/0216/115.html?1455860390
Edis is heavily used in distributed environments, and how locks are resolved in a natural distributed environment immediately becomes a problem. For example, our current hand tour project, server side is divided by Business module server, there are application services, combat clothing, etc., but these two VMS can also change the player's properties, which if under the same VM, it is easy to lock, but if in a distributed environment is not so easy, Of course, there are solutions to the existing features of Redis, such as the Redis script.
Redis adds the functionality of Lua scripting to the 2.6 release, and can execute LUA scripts directly in the Redisserver environment with the eval command, and you can invoke the Redis command in a LUA script.
Benefits of using scripts:
1. Reduce network overhead: You can send some of the functions to be processed in batch, execute in a script, reduce the number of interactions between client and Redis.
2. Atomic operation: This is mainly the function we use here, in the distributed environment to ensure the atomicity of data.
3. Multiplexing: Scripts sent by clients are stored permanently in Redis, which means that other clients can reuse the script without having to use code to complete the same logic.
Let's look at a LUA script:
The code is as follows:
Local Food=redis.call (' Hget ', keys[1], ' food ');
FOOD=FOOD+ARGV[1];
Redis.call (' Hset ', keys[1], ' food ', food);
Local Diamond=redis.call (' Hget ', keys[1], ' diamond ');
DIAMOND=DIAMOND+ARGV[2];
Redis.call (' Hset ', keys[1], ' Diamond ', diamond);
Note: Redis.call is the Redis command that we call in the script, the keys and ARGV2, respectively, are keys and parameters, the subscripts are all starting from 1, not 0.
The function of this script is to remove the player's food (grain) and diamond (Jade) specified by the keys, then modify the line, and finally save in Redis, the execution of the script guarantees the atomicity of the whole operation.
Let's take a look at the specific implementation process using Java code.
The code is as follows:
Jedis Jedis = new Jedis ("192.168.128.128", 6379);
1. Initial player data to Redis
Gameplayer player = new Gameplayer ();
Player.setid (1001);
Player.setname ("Ksfzhaohui");
Player.setfood (100);
Player.setdiamond (100);
map<string, string> beanmap = beanutil.warp (player);//convert object to map
String Beankey = Getredisbeankey (Player.getclass (), Player.getid ());
System.out.println ("key:" + Beankey);
Jedis.hmset (Beankey, beanmap);//save player data to Redis
First simulates a player to save the player information in Redis, the ID of this side to write a random, under normal circumstances are through the Redis command INCR generate an ID
Results:
The code is as follows:
String script = "Local Food=redis.call (' Hget ', keys[1], ' food ');"
+ "food=food+argv [1]; "
+ "Redis.call (' Hset ', keys[1], ' food ', food);
+ "local diamond= Redis.call (' Hget ', keys[1], ' diamond ');
+ "diamond= DIAMOND+ARGV[2]; "
+ "Redis.call (' Hset ', keys[1], ' Diamond ', diamond);
list<string> keys = new arraylist<string> ();
Keys.add (Beankey);
List<string> args = new arraylist<string> ();
Args.add ("100");
Args.add ("100");
//3. Execute script
Jedis.eval (script, keys, args);
Specify key and reference, execute script, result:
Beanutil Code:
The code is as follows:
public class Beanutil {
private static Logger Logger = Logger.getlogger (Beanutil.class);
private static final String class = "Class";
/**
* Encapsulates the specified object data into a map
*
* @param Bean
* Object Data
* @return
*/
@SuppressWarnings ("All")
public static map<string, string> warp (Object Bean) {
map<string, string> propertymap = new hashmap<string, string> ();
try {
Propertydescriptor[] PS = Introspector.getbeaninfo (Bean.getclass ())
. Getpropertydescriptors ();
for (PropertyDescriptor Propertydescriptor:ps) {
String propertyname = Propertydescriptor.getname ();
if (propertyname! = null &&!propertyname.equals (CLASS)) {
Method getter = Propertydescriptor.getreadmethod ();
if (getter! = null) {
Propertymap.put (PropertyName,
String.valueof (Getter.invoke (bean, NULL)));
}
}
}
} catch (Exception e) {
Logger.error (e);
}
return propertymap;
}
}
Using Java scripts to implement distributed locks in Redis