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)

相关推荐

  • Linux下Redis数据库的安装方法与自动启动脚本分享

    安装Redis  (1) 下载Redis wget http://redis.googlecode.com/files/redis-2.2.11.tar.gz tar xzvf redis-2.2.11.tar.gz  (2) 编译并安装Redis make && make install  (3) 复制并修改配置文件 cp redis.conf /etc/redis.conf vi /etc/redis.conf 注意修改以下几项: daemonize yes loglevel warn

  • redis常用命令、常见错误、配置技巧等分享

    1. redis查看当前所有的key 复制代码 代码如下: KEYS * 2. 查看当前redis的配置信息 复制代码 代码如下: CONFIG GET * 3. MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis

  • Redis实现唯一计数的3种方法分享

    唯一计数是网站系统中十分常见的一个功能特性,例如网站需要统计每天访问的人数 unique visitor (也就是 UV).计数问题很常见,但解决起来可能十分复杂:一是需要计数的量可能很大,比如大型的站点每天有数百万的人访问,数据量相当大:二是通常还希望扩展计数的维度,比如除了需要每天的 UV,还想知道每周或每月的 UV,这样导致计算十分复杂. 在关系数据库存储的系统里,实现唯一计数的方法就是 select count(distinct <item_id>),它十分简单,但是如果数据量很大,这

  • 详解StackExchange.Redis通用封装类分享

    前两天朋友问我,有没有使用过StackExchange.Redis,问我要个封装类,由于之前都是使用ServiceStack.Redis,由于ServiceStack.Redis v4版本后是收费版的,所以现在也很有公司都在使用StackExchange.Redis而抛弃ServiceStack.Redis了.其实个人觉得,两个驱动都不错,只是由于ServiceStack.Redis收费导致目前很多公司都是基于V3版本的使用,也有人说V3版本有很多Bug,没有维护和升级,不过至少目前我是没发现B

  • Ubuntu下安装redis的2种方法分享

    前言 redis是目前公认的速度最快的基于内存的键值对数据库,但redis的缺点也非常明显,仅提供最基本的hash set, list, sorted set等基于数据类型,不分表,没有schema,没有索引,没有外键,缺少int/date等基本数据类型,多条件查询需要通过集合内联(sinter,zinterstore)和连接间接实现,操作不便,开发效率低,可维护性不佳: 因此一般不将其视为完整的数据库单独使用,很多网站将redis作为高速缓存和session状态存储层,然后再与其他数据库搭配使

  • PHP 使用redis简单示例分享

    示例很简单,注释里也都做了说明,这里就不多废话了. 复制代码 代码如下: <?php /*从平台获取数据库名*/ $dbname = ""; /*从环境变量里取host,port,user,pwd*/ $host = ''; $port = ''; $user = ''; $pwd = ''; try {     /*建立连接后,在进行集合操作前,需要先进行auth验证*/     $redis = new Redis();     $ret = $redis->conne

  • RedisRepository 分享和纠错

    一.   写在前面 毕业工作后,今天终于能回家了,回想了一些这半年来所做的内容,总是觉得还停留在那么基础的水平 ,在解决各种问题的过程中,自己的创新思路比较少,靠搜索来的比较多 .不想做16年的总结了 ,希望17年能学更多的我爱的技术,看更多的开源代码,能学到更多的设计思想和代码思路,能再更新这两年来对代码的理解. 这篇分享,主要是弥补我之前RedisRepository的不足. 半年前由于我StackExchange.Redis文档阅读不足,所分享的RedisRepository有所错误.下面

  • php操作redis缓存方法分享

    php redis缓存操作 <?php /** * Redis缓存操作 * @author hxm * @version 1.0 * @since 2015.05.04 */ class RCache extends Object implements CacheFace { private $redis = null; //redis对象 private $sId = 1; //servier服务ID private $con = null;//链接资源 /** * 初始化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.

  • 高效的数据同步工具DataX的使用及实现示例

    目录 前言 一.DataX 简介 1.DataX3.0 框架设计 2.DataX3.0 核心架构 二.使用 DataX 实现数据同步 1.Linux 上安装 DataX 软件 2.DataX 基本使用 3.安装 MySQL 数据库 4.通过 DataX 实 MySQL 数据同步 5.使用 DataX 进行增量同步 前言 我们公司有个项目的数据量高达五千万,但是因为报表那块数据不太准确,业务库和报表库又是跨库操作,所以并不能使用 SQL 来进行同步.当时的打算是通过 mysqldump 或者存储的

  • Redis和数据库 数据同步问题的解决

    缓存充当数据库 比如说Session这种访问非常频繁的数据,就适合采用这种方案:当然了,既然没有涉及到数据库,那么也就不会存在一致性问题: 缓存充当数据库热点缓存 读操作 目前的读操作有个固定的套路,如下: 客户端请求服务器的时候,发现如果服务器的缓存中存在,则直接取服务器的: 如果缓存中不存在,则去请求数据库,并且将数据库计算出来的数据回填给缓存: 返回数据给客户端: 写操作 各种情况会导致数据库和缓存出现不一致的情况,这就是缓存和数据库的双写一致性问题: 目前缓存存在三种策略,分别是 Cac

  • java制作复制文件工具代码分享

    复制代码 代码如下: package com.robin; import java.io.File;import java.io.FileInputStream;import java.io.FileWriter;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Properties; public class FileCopy { // priv

  • c语言实现系统时间校正工具代码分享

    复制代码 代码如下: //*******************************************************************//Time Protocol是一种非常简单的应用层协议.它返回一个未格式化的32位二进制数字, //这个数字描述了从1900年1月1日午夜到现在的秒数.服务器在端口37监听协议请求,以 //TCP/IP或者UDP/IP格式返回响应.将服务器的返回值转化为本地时间是客户端程序的责任. //这里使用的时间服务器是129.132.2.21,更

  • c#实现网页图片提取工具代码分享

    复制代码 代码如下: public Array MatchHtml(string html,string com)       {           List<string> urls = new List<string>();           html = html.ToLower();           //获取SRC标签中的URL           Regex regexSrc = new Regex("src=\"[^\"]*[(.j

  • Scott 数据 映射 MySQL代码实现分享

    目录 1.SQL 2.实体类 2.1.Dept.java 2.2.Emp.java 3.数据库模拟代码 1.SQL DROP TABLE IF EXISTS `tb_dept`; CREATE TABLE `tb_dept`  (   `deptno` tinyint(2) UNSIGNED NOT NULL  COMMENT '部门编号',   `dname` varchar(14) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT

  • MySQL 到Oracle 实时数据同步

    目录 第一步:配置MySQL 连接 第二步:配置 Oracle连接 第四步:进行数据校验 其他数据库的同步操作 摘要:很多 DBA 同学经常会遇到要从一个数据库实时同步到另一个数据库的问题,同构数据还相对容易,遇上异构数据.表多.数据量大等情况就难以同步.本文亲测了一种方式,可以非常方便地完成 MySQL 数据实时同步到Oracle,跟大家分享一下,希望对你有帮助. 本次 MySQL 数据实时同步到 Oracle大概只花了几分钟就完成.使用的工具是Tapdata Cloud ,这个工具是永久免费

  • MySQL 到 ClickHouse 实时数据同步实操

    摘要: 很多 DBA 同学经常会遇到要从一个数据库实时同步到另一个数据库的问题,同构数据还相对容易,遇上异构数据.表多.数据量大等情况就难以同步.我自己亲测了一种方式,可以非常方便地完成 MySQL 数据实时同步到ClickHouse,跟大家分享一下,希望对你有帮助. MySQL 到 ClickHouse 实时数据同步实操分享 本次 MySQL 数据实时同步到ClickHouse大概只花了几分钟就完成.使用的工具是Tapdata Cloud ,这个工具是永久免费的. @[TOC](MySQL 到

  • MySQL 到Oracle 实时数据同步

    目录 第一步:配置MySQL 连接 第二步:配置 Oracle连接 第四步:进行数据校验 其他数据库的同步操作 摘要:很多 DBA 同学经常会遇到要从一个数据库实时同步到另一个数据库的问题,同构数据还相对容易,遇上异构数据.表多.数据量大等情况就难以同步.本文亲测了一种方式,可以非常方便地完成 MySQL 数据实时同步到Oracle,跟大家分享一下,希望对你有帮助. 本次 MySQL 数据实时同步到 Oracle大概只花了几分钟就完成.使用的工具是Tapdata Cloud ,这个工具是永久免费

随机推荐