redis实现多进程数据同步工具代码分享
package com.happyelements.odin.util;
import static com.google.common.base.preconditions.checknotnull;
import org.jetbrains.annotations.notnull;
import com.happyelements.odin.jedis.jedisclient;
import com.happyelements.rdcenter.commons.util.datetimeutil;
/**
* user: jude.wang
* date: 14-1-16
* time: 上午9:43
*/
public class concurrentutil {
public static final string user_lock_key_format = "user_lock_%d_%s";
public static final string custom_lock_format = "custom_lock_%s";
public static final jedisclient redisclient = jedisclient.getinstance();
public static final string unlocked = "0";
public static final string locked = "1";
private static final int max_repeat_times = 10;
@notnull
public static string builduserlockkey(long userid, @notnull string key) {
checknotnull(key);
return string.format(user_lock_key_format, userid, key);
}
@notnull
public static string buildcustomlockkey(@notnull string key) {
checknotnull(key);
return string.format(custom_lock_format, key);
}
/**
* 此方法可以因为拿不到锁而导致operation没有执行
*
* @param key
* @see com.happyelements.odin.util.concurrentutil#buildcustomlockkey(string)
* @see com.happyelements.odin.util.concurrentutil#builduserlockkey(long, string)
*
* @param operation
* @throws com.happyelements.odin.util.concurrentutil.operationnotexecexception
* operation没有被执行
*/
public static void dojobwithlock(@notnull string key, @notnull ilockoperation operation) throws operationnotexecexception {
boolean locked = false;
try {
checknotnull(key);
checknotnull(operation);
locked = lock(key);
} catch (throwable t) {
throw new operationnotexecexception(key, t);
}
try {
if (locked) {
// system.out.println(thread.currentthread() + "\t" + "lock");
operation.dojob();
} else {
throw new operationnotexecexception(key);
}
} finally {
if (locked) {
unlock(key);
}
}
}
private static void unlock(string key) {
try {
checknotnull(key);
string oldstatus = redisclient.getset(key, unlocked);
if (isunlocked(oldstatus)) {
// lock->dojob->过期->unlock
// todo log
}
} catch (throwable t) {
// todo log
}
// system.out.println(thread.currentthread() + "\t" + "unlock");
}
private static boolean isunlocked(string status) {
return status == null || status.equals(unlocked);
}
private static boolean lock(string key) {
boolean locked = false;
for (int i = 0; i < max_repeat_times; i++) {
string oldstatus = redisclient.getset(key, locked);
if (isunlocked(oldstatus)) {
if (oldstatus == null) {
redisclient.expire(key, datetimeutil.minute_second * 5);
locked = true;
break;
}
locked = true;
break;
}
}
return locked;
}
public static interface ilockoperation {
void dojob();
}
/**
* {@link com.happyelements.odin.util.concurrentutil.ilockoperation#dojob()}没有被执行
* 上层必须处理该异常,捕获到该异常可以retry本次操作,或者包装成{@link com.happyelements.rdcenter.commons.throwable.heexception} 抛出去
*/
public static class operationnotexecexception extends exception {
public operationnotexecexception() {
}
public operationnotexecexception(string s) {
super(s);
}
public operationnotexecexception(string s, throwable throwable) {
super(s, throwable);
}
public operationnotexecexception(throwable throwable) {
super(throwable);
}
}
}