今天龍哥和俊哥在探討分布式數據層的問題,會有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 日午夜(通用時間)以來的毫秒數。
但這個還會有問題