java redis的同步_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);

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值