Implement distributed locks using Redis scripts
Redis is widely used in distributed environments. It is a problem immediately to solve the locks in distributed environments. For example, in our current mobile game project, servers are divided by business modules, including application servers and combat servers. However, both VMS may change the player attributes at the same time, if it is under the same vm, it is easy to lock, but it is not so easy in a distributed environment. Of course, there are also solutions to use the existing functions of redis, for example, redis script.
Redis Versions later than 2.6 have added the Lua Script Function. You can run the Lua script directly in the RedisServer environment using the eval command and call the Redis command in the Lua script.
Advantages of using scripts:
1. reduce network overhead: some features to be processed in batches can be sent to a script for execution, reducing the number of interactions between the client and redis.
2. atomic operation: This is the main feature we use here to ensure data Atomicity in a distributed environment.
3. Reuse: scripts sent by the client are permanently stored in redis. This means that other clients can reuse the script without using code to complete the same logic.
Next, let's take a look at a lua 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 );
Note: redis. call is the redis command we call in the script. The KEYS and ARGV2 arrays are KEYS and parameters respectively, and the subscript starts from 1, not 0.
The function of this script is to take out the food and diamond (JADE) players specified by KEYS, modify them, and save them in redis. The script is executed, guarantees the atomicity of the entire operation.
Next we will use java code to look at the specific implementation process
Jedis jedis = new Jedis ("192.168.128.128", 6379 );
// 1. The initial gamer data is sent 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); // converts an object to a map
String beanKey = getRedisBeanKey (player. getClass (), player. getId ());
System. out. println ("key:" + beanKey );
Jedis. hmset (beanKey, beanMap); // save player data to redis
First, a player is simulated to save the player information in redis. The Id here is written at will. Normally, an id is generated through the redis command incr.
Result:
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 the script
Jedis. eval (script, keys, args );
Specify the key and reference, and execute the script. Result:
BeanUtil code:
Public class BeanUtil {
Private static Logger logger = Logger. getLogger (BeanUtil. class );
Private static final String CLASS = "class ";
/**
* Encapsulate 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;
}
}
Of course, there are other methods on the Internet, such as using SETNX to implement distributed locks.
Refer:
Install and test Redis in Ubuntu 14.04
Redis cluster details
Install Redis in Ubuntu 12.10 (graphic explanation) + Jedis to connect to Redis
Redis series-installation, deployment, and maintenance
Install Redis in CentOS 6.3
Learning notes on Redis installation and deployment
Redis. conf
Redis details: click here
Redis: click here
This article permanently updates the link address: