MYSQL锁表的用法,防止并发情况下的重复数据

项目中有些使用的redis存储,当对redis进行rehash的时候感觉是比较麻烦的。于是写了个简单的读取redis到数据库的关键方法。仅供参考。

package com.redis.web;

import java.util.Date;
import java.util.Iterator;
import java.util.Set;

import redis.clients.jedis.Jedis;

import com.redis.entity.RedisTable;

public class RedisPersistence {
	/**
	 * 存储所有的redis对象方法
	 */
	public static void saveAllRedis(final String redisIp,final int redisPort,final String appCode) {
		Jedis redis = new Jedis(redisIp, redisPort);// 连接redis
		// redis.auth("redis");//验证密码
		// KEY操作
		Set keys = redis.keys("*");// 列出所有的key,查找特定的key如:redis.keys("foo")
		Iterator t1 = keys.iterator();
		while (t1.hasNext()) {
			Object obj1 = t1.next();
			saveRedisObject(redis, obj1 + "", redisIp, redisPort + "", appCode);
		}
	}
	
	/**
	 * 存储单个对象
	 * @param redis
	 * @param redisKey
	 * @param macIp
	 * @param port
	 * @param appCode
	 */
	private static void saveRedisObject(final Jedis  redis,final String redisKey,final String macIp,final String port,final String appCode) {
		String redisType = redis.type(redisKey);
		RedisTable redisTable = new RedisTable();
		redisTable.setAppCode(appCode);
		redisTable.setCreateTime(new Date());
		redisTable.setMacIp(macIp);
		redisTable.setPort(port);
		redisTable.setRedisKey(redisKey);
		redisTable.setRedisType(redisType);
		redisTable.setRemark("");
		redisTable.setUpdateTime(new Date());
		//set集合
		if("set".equalsIgnoreCase(redisType)){
			Set<String> setStrings  = redis.smembers(redisKey);//获取key的所有set集合
			if(null != setStrings && !setStrings.isEmpty()){
				Iterator setIterator = setStrings.iterator() ;   
		           while(setIterator.hasNext()){   
		               Object obj1 = setIterator.next();  
		               redisTable.setRedisValue(obj1+"");
		               printRedis(redisTable);//保存每一个set记录
		           }  
			}
		//hash集合
		}else if("hash".equalsIgnoreCase(redisType)){
			Set<String> hashSets = redis.hkeys(redisKey);
			if(null != hashSets && !hashSets.isEmpty()){
				Iterator setIterator = hashSets.iterator() ;   
		           while(setIterator.hasNext()){   
		               String objectName = setIterator.next()+"";  
		               redisTable.setObjectName(objectName);
		               redisTable.setRedisValue(redis.hget(redisKey, objectName));
		               printRedis(redisTable);//保存每一个set记录
		           }  
			}
		//list集合
		}else if("list".equalsIgnoreCase(redisType)){
			Long listLen = redis.llen(redisKey);
			for (Long i = 0L; i < listLen; i++) {
				redisTable.setRedisValue(redis.lindex(redisKey, i));
				printRedis(redisTable);
			}
		//sortedset集合
		}else if("sortedset".equalsIgnoreCase(redisType)){
//			Long redisLenth = redis.zcard(redisKey);
			Set<String> sortedsets = redis.zrange(redisKey, 0, -1);
			if(null != sortedsets && !sortedsets.isEmpty()){
				Iterator setIterator = sortedsets.iterator() ;   
		           while(setIterator.hasNext()){   
		               String sortedMember = setIterator.next() +"";  
		               redisTable.setRedisValue(sortedMember);
		               redisTable.setScore("" +redis.zscore(redisKey, sortedMember));
		               printRedis(redisTable);//保存每一个sortedset记录
		           }  
			}
		//string集合
		}else if("string".equalsIgnoreCase(redisType)){
			redisTable.setRedisValue(redis.get(redisKey));
			printRedis(redisTable);//保存记录
		}else{
			System.out.println("UnknowRedisType-----redisType: " +redisType+"      objValue: "+redis.get(redisKey));
		}
	}

	//打印输出
	public static void printRedis (RedisTable redisTable) {
		System.out.println("redisType:"+redisTable.getRedisType()  
						+ " redisKey:"+redisTable.getRedisKey()
						+ " ObjectName:"+redisTable.getObjectName()
						+ " redisValue:"+redisTable.getRedisValue()
						+ " redisScore:"+redisTable.getScore()
		);
	}
	
	public static void main(String[] args) {
		String redisIp = "127.0.0.1";//redis的IP地址
		int redisPort = 6379;//redis的端口号
		String appCode = "FUYOU";//根据不同的应用区分的appcode
		saveAllRedis(redisIp,redisPort,appCode);
	}
}


其中的appCode是不需要的,这里只是为了针对于不同的应用,可以使用同一个redis进行持久化备份而已(通过appcode来区分)。

其中使用的RedisTable实例如下:

package com.redis.entity;

import java.util.Date;

public class RedisTable {
    private Long redisId; //保存redis的主键ID
    private String redisType;//redis的类型如:set/list/hash/sortedset/string
    private String redisKey;//保存redis时使用的key
    private String objectName;//此属性主要用于hash数据结构时,保存member的
    private String redisValue;//存储的redis的值
    private String keyToken;//保存Token时,为区分拼接的字符串
    private String score;//此属性为sortedset数据结构时,保存的score值
    private Date createTime;//创建时间
    private Date updateTime;//更新时间
    private String macIp;//redis的IP地址  当然此处也可以存储mac地址
    private String port;//redis使用的端口号
    private String appCode;//应用区分码
    private String remark;//备注
    private String isModify;//是否修改。此属性可以用于增量备份时,即在每个redis存储时可以更具key多存储一个属性isModify。 如果有修改,则置为 Y,否则为N.
    
///////////////////////此处省略 setter  and getter 方法////////////////////////


}



以上方法可以扩充用于redis备份中心。

在使用redis增量备份时,请根据rediskey在数据块中查找是否存在。根据更新值返回的0或者是1,进行更新或者新增的操作。

当然数据库的表结构目前只是一张表,如果数据量很大的情况下,可以将端口、IP、appCode信息存储到单独的一张表,减少数据冗余。

以上的时间复杂度以及效率上并没有优化。如果要求比较高,请自行优化。


希望各位大侠给出建议,共同进步!





MYSQL锁表的用法,防止并发情况下的重复数据

上一篇:Java实现Redis持久化到数据库的关键方法


下一篇:安装SQL2012出现报错: 启用 Windows 功能 NetFx3 时出错