20150325 向Redis存入Map涉及的key值生成问题

时间:2022-06-10 19:17:08

今天龙哥和俊哥在探讨分布式数据层的问题,会有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 日午夜(通用时间)以来的毫秒数。

但这个还会有问题

20150325 向Redis存入Map涉及的key值生成问题

20150325 向Redis存入Map涉及的key值生成问题