今天龙哥和俊哥在探讨分布式数据层的问题,会有mycat管理的mysql集群,Redis内存数据库存储,还有一个数据代理层用于同步mysql和redis的数据和比对,为了各个模块的数据解耦,决定数据传输时传的是list或是map,这样不用确保各个模块如果是类定义的话,各个模块的类的结构定义必须是相同的(假如传对象的话,假如是订单,各个模块的订单类都需要相同),这样是数据耦合的,这样我的Redis这一部分就要求能够在消息队列传过来一个map,我可以调用我的webservice存入Redis集群中,webservice是注册在ESB上。
这样存的方法有两种,一种是存入map,自己方法中生成个key,然后存入Redis中,一种是传过来时直接给了订单id和map,订单Id作为key,这样存。
这样就存在了生产key的方法,这个key不能是重复的,开始想到的生成不重复的随机数。在网上找了个例子,
package redisTest; import java.util.Random; public class RadomUtil { public static int Key = 100; public String getKey(){ String key = "key"+(Key++); return key; } //设定几位数 private static final int LENGTH = 8; /** * 这是典型的随机洗牌算法。 * 流程是从备选数组中选择一个放入目标数组中,将选取的数组从备选数组移除(放至最后,并缩小选择区域) * 算法时间复杂度O(n) * @return 随机8为不重复数组 */ public static String generateNumber() { String no = ""; // 初始化备选数组 int[] defaultNums = new int[10]; for (int i = 0; i < defaultNums.length; i++) { defaultNums[i] = i; } Random random = new Random(); int[] nums = new int[LENGTH]; // 默认数组中可以选择的部分长度 int canBeUsed = 10; // 填充目标数组 for (int i = 0; i < nums.length; i++) { // 将随机选取的数字存入目标数组 int index = random.nextInt(canBeUsed); nums[i] = defaultNums[index]; // 将已用过的数字扔到备选数组最后,并减小可选区域 swap(index, canBeUsed - 1, defaultNums); canBeUsed--; } if (nums.length > 0) { for (int i = 0; i < nums.length; i++) { no += nums[i]; } } return no; } /** * 交换方法 * @param i 交换位置 * @param j 互换的位置 * @param nums 数组 */ private static void swap(int i, int j, int[] nums) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; }
/** * 获取8位数 * @return */ public static String generateNumber2() { String no = ""; int num[] = new int[8]; int c = 0; for (int i = 0; i < 8; i++) { num[i] = new Random().nextInt(10); c = num[i]; for (int j = 0; j < i; j++) { if (num[j] == c) { i--; break; } } } if (num.length > 0) { for (int i = 0; i < num.length; i++) { no += num[i]; } } return no; } }
主要的意思是先生成一个生成几个随机数数组,用的时候将用过的随机数放在一个用过的数组中,随出的随机数在用过的随机数数组中比较下,看是否重复,如果重复,将该随机数在可用数组中删掉。此方法适合一次调用生成多个随机数,和把生成的随机数放在set里是一个意思,但是不适合,我的想法,我的是每次来了一个map 都要调用程序生成一个不同的key,存入Redis中,但是每次调用上面的程序都会生成一个随机数,但不能保证,每次生成的随机数都是不同的,因为每次调用生产随机数都会从新启动程序,这样每次程序中用过的随机数这个数组都会从新清零,因为每次调用完,该程序就结束了,不能保存该数组,同理set也是这个道理。
然后我又想到第二种方法,就是在Redis中保存一个key值,每次存入一个map,该key值+1,像计数器一样,但这样存入map时,需要先去Redis中读这个key然后还得改这个key,这样没有在方法中直接获取key效率高。
第三种方法:取时间作为key,但是要有锁,以免多个线程来取时间时,产生相同时间值。
String key = null; Lock lock = new ReentrantLock(); try{ lock.lock(); key = new Date().getTime()+""; }finally{ lock.unlock(); }
Date().getTime()方法取到的是距离1970 年1 月1 日午夜(通用时间)以来的毫秒数。
但这个还会有问题