Redis script implements distributed locks

original
2015/01/11 19:19
Reading amount 1.1W

Redis is widely used in distributed environments. Naturally, how to solve locks in distributed environments becomes a problem immediately. For example, in our current mobile game project, the server side is divided into servers by business module, including application server and combat server. However, these two vms may change the attributes of players at the same time. If they are under the same vm, it is easy to lock them, but it is not so easy in a distributed environment. Of course, there are solutions using the existing functions of Redis, For example, the script of Redis.

Redis has added the function of Lua script in versions after 2.6. You can directly execute Lua script in the RedisServer environment through the eval command, and you can call Redis commands in the Lua script.
Benefits of using scripts:
1. Reduce network overhead: some functions to be processed in batches can be sent to a script for execution, reducing the number of interactions between the client and Redis
two Atomic operation : This is mainly the function we use here to ensure the atomicity of data in a distributed environment.
3. Reuse: The script sent by the client will be permanently stored in Redis, which means that other clients can reuse this script without using code to complete the same logic.

Let's 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 means that we call the redis command in the script. KEYS and ARGV2 arrays are keys and parameters, respectively. Subscripts start from 1, not 0.
The function of this script is to take out the food and diamond of players designated by KEYS, modify them, and save them in Redis. The execution of the script ensures the atomicity of the whole operation.

Let's use java code to see the specific implementation process

 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, a player is simulated to save the player information in Redis, and an ID is randomly written here. Normally, an ID is generated through the command incr of Redis
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 script jedis.eval(script, keys, args);

Specify the key and reference, execute the script, and the result is:

BeanUtil code:

 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; } }

Of course, there are other methods online, such as: Implementing distributed locks with SETNX
Refer to: http://phl.iteye.com/blog/2029944

Personal blog: http://codingo.xyz

Expand to read the full text
Loading
Click to join the discussion 🔥 (9) Post and join the discussion 🔥
nine comment
one hundred and thirty-seven Collection
fourteen fabulous
 Back to top
Top