20150325 向Redis存入Map涉及的key值生成問題


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

但這個還會有問題

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM