首页 > 代码库 > 分布式部署应用时主从同步时候主键重复

分布式部署应用时主从同步时候主键重复

原因:

解决方法: 用redis生成主键

/**     *      * @Title: getContractId     * @user: zzx     * @time: 2016年11月15日下午5:36:15     * //DESC 获取订单ID     * @param param step:步长     * @return 当前分布式环境下最新ID     * @return String  返回类型     * @throws     */    public String getContractId(JSONObject param){    	int step = param.getIntValue("step");    	Long current = productContractIdAutomic.longValue();    	Long newValue = http://www.mamicode.com/current + step;"hljs-string">"success");        rs.setResult_data(String.valueOf(current));        return JSON.toJSONString(rs);    }

全部代码:

package com.eshore.ismp.cache.processor;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import javax.annotation.Resource;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.support.atomic.RedisAtomicLong;import org.springframework.stereotype.Service;import org.springframework.util.StringUtils;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONArray;import com.alibaba.fastjson.JSONObject;import com.eshore.ismp.cache.redis.RedisService;import com.eshore.ismp.common.entity.ResultInfo;/** * 订单模块缓存接口. * @author zhangjunyong * @version V1.0  2016/9/2 12:04 */@Servicepublic class ContractProcessor {    private static final Logger logger = Logger.getLogger(ContractProcessor.class);    private static final String KEY = "key";    private static final String VALUE = http://www.mamicode.com/"value";    private static final String SIZE = "size";        @Autowired    RedisService redisService;        @Resource(name="productContractIdAutomic")	private RedisAtomicLong productContractIdAutomic;        /**     * 订单模块,用于存放数据进list.     * @param param     * @return String     * @author zhangjunyong     * @date 2016/9/2 12:05     */    public String putToList(JSONObject param) {        ResultInfo rs = new ResultInfo();        try {            String key = param.getString(KEY);            JSONArray array = param.getJSONArray(VALUE);            if (array == null || array.isEmpty() || StringUtils.isEmpty(key)) {                logger.error("参数错误");                rs.setResult_code(4501);                rs.setResult_detail("参数错误");                return JSON.toJSONString(rs);            }            List<String> valueList = new ArrayList<String>();            for (Object value : array) {                valueList.add(String.valueOf(value));            }            long result = redisService.rpush(key, valueList);            rs.setResult_code(0);            rs.setResult_detail("success");            rs.setResult_data(String.valueOf(result));            return JSON.toJSONString(rs);        } catch (Exception e) {            rs.setResult_code(4502);            rs.setResult_detail("系统错误!");            logger.info("An error occur when invoke method putToList", e);            return JSON.toJSONString(rs);        }    }    /**     * 批量弹出列表中数据.     * @param param     * @return String     * @author zhangjunyong     * @date 2016/9/2 12:06     */    @SuppressWarnings("rawtypes")    public String getFromList(JSONObject param) {        ResultInfo rs = new ResultInfo();        try {            String key = param.getString(KEY);            int size = param.getInteger(SIZE);            if (StringUtils.isEmpty(key) || size == 0) {                logger.error("参数错误");                rs.setResult_code(4501);                rs.setResult_detail("参数错误");                return JSON.toJSONString(rs);            }            List data = http://www.mamicode.com/redisService.lpop(key, size);            rs.setResult_code(0);            rs.setResult_detail("success");            rs.setResult_data(JSON.toJSONString(data));            return JSON.toJSONString(rs);        } catch (Exception e) {            rs.setResult_code(4502);            rs.setResult_detail("系统错误!");            logger.info("An error occur when invoke method getFromList", e);            return JSON.toJSONString(rs);        }    }    /**     * 批量存放hash对象到key中.     * @param param     * @return String     * @author zhangjunyong     * @date 2016/9/2 12:06     */    public String putToHash(JSONObject param) {        String key = param.getString(KEY);        JSONArray array = param.getJSONArray(VALUE);        ResultInfo rs = new ResultInfo();        if (array == null || array.isEmpty() || StringUtils.isEmpty(key)) {            logger.error("参数错误");            rs.setResult_code(4501);            rs.setResult_detail("参数错误");            return JSON.toJSONString(rs);        }        Map<String, String> valueMap = new HashMap<String, String>();        for (Object value : array) {            JSONObject jsObj = JSON.parseObject(String.valueOf(value));            logger.info("jsonObj : = " + jsObj.toJSONString());            logger.info("key=" + jsObj.getString("key") + " value="http://www.mamicode.com/+ jsObj.getString("value"));            valueMap.put(jsObj.getString("key"), jsObj.getString("value"));        }        int result = redisService.hmset(key, valueMap);        rs.setResult_code(0);        rs.setResult_detail("success");        rs.setResult_data(String.valueOf(result));        return JSON.toJSONString(rs);    }        /**     *      * @Title: getContractId     * @user: zzx     * @time: 2016年11月15日下午5:36:15     * //DESC 获取订单ID     * @param param step:步长     * @return 当前分布式环境下最新ID     * @return String  返回类型     * @throws     */    public String getContractId(JSONObject param){    	int step = param.getIntValue("step");    	Long current = productContractIdAutomic.longValue();    	Long newValue = http://www.mamicode.com/current + step;"hljs-keyword">new ResultInfo();    	rs.setResult_code(0);        rs.setResult_detail("success");        rs.setResult_data(String.valueOf(current));        return JSON.toJSONString(rs);    }}

调用方法

package com.eshore.ismp.contract.sql;import org.apache.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Component;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.eshore.ismp.common.entity.ResultInfo;import com.eshore.ismp.common.thrift.CacheService.Iface;@Component@Scope("prototype")public class IDManager {	private static final Logger logger = Logger.getLogger(IDManager.class);		@Autowired	private Iface cacheServer;	private static final int STEP = 200;	private static String GET_ID_METHOD = "contract.getContractId";	private Long current = 0L;	private Long end = 0L;		/**	 * 	 * @Title: getId	 * @user: zzx	 * @time: 2016年11月15日下午7:45:52	 * //DESC 通过缓存获取ID	 * @param type	 * @return	 * @return Long  返回类型	 * @throws	 */	public synchronized Long getId(final int type) {		if (this.end <= this.current) {			JSONObject param = new JSONObject();			param.put("step", STEP);			try {				String resultInfo =cacheServer.process(GET_ID_METHOD, param.toJSONString());				ResultInfo ri = JSON.parseObject(resultInfo, ResultInfo.class);				if(ri.getResult_code() ==0){					current =Long.parseLong(ri.getResult_data())+1;					end = current + STEP;				}							} catch (Exception e) {				logger.error("get id error:",e);				return null;			}		}		return this.current++;	}}

如果表中存在历史数据,则需要开个定时器将id初始值设置大一点或者直接在数据库改掉redis的初始值然后重启服务

 

分布式部署应用时主从同步时候主键重复