这是昨天参加复试的时候,技术问的:
一、
您有么有一种办法来代替UUID,就是说保证全球无重复!
Ps:不用说用 时间 + 随机字符,就是这么说的,技术说那也可能有重复的!
不用说 Base64或Base58,这个也是基于UUID的
现在说的是你自己创造的"UUID"
二、
Oracle中有Sequence,那么您如何在不用Sequence的情况下,做出类似Sequence的效果呢?比方说我当前的最大Id是5,那么下一个应该就是6,但是我1秒可能有上百万的数据存入,您如何实现呢JavaOracleSequenceUUID

解决方案 »

  1.   

    一、除了你说的2种我想不出来,坐等答案。
    二、可以自己写Sequence生成器。我项目中用的:import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.HashMap;
    import java.util.Map;/**
    *
    * <b>Note</b>: Java实现的Sequence工具
    */
    public class SequenceUtil {
            
            /**
             * 单例模式
             */
            private static SequenceUtil instance = new SequenceUtil();
            
            /**
             * 存放序列的MAP
             */
            private Map<String, KeyInfo> keyMap = new HashMap<String, KeyInfo>(20);
            private static final int POOL_SIZE = 1;        /**
             * 防止外部实例化
             */
            private SequenceUtil() {
            }        /**
             * 单例模式,获取单例
             *
             * @return SequenceUtils的单例对象
             */
            public static SequenceUtil getInstance() {
                    return instance;
            }        /**
             * 获取下一个sequence值
             *
             * @param keyName
             * Sequence名称
             * @return 下一个Sequence键值
             */
            public synchronized int getNextKeyValue(String keyName) {
                    KeyInfo keyInfo = null;
                    Integer keyObject = null;
                    try {
                            if (keyMap.containsKey(keyName)) {
                                    keyInfo = keyMap.get(keyName);
                            } else {
                                    keyInfo = new KeyInfo(keyName, POOL_SIZE);
                                    keyMap.put(keyName, keyInfo);
                            }
                            keyObject = keyInfo.getNextKey();
                    } catch (SQLException e) {
                            e.printStackTrace();
                    }
                    return keyObject;
            }
    }class KeyInfo {
            
            /**
             * 当前Sequence载体的最大值
             */
            private int maxKey;
            
            /**
             * 当前Sequence的最小值
             */
            private int minKey;
            
            /**
             * 下一个Sequence值
             */
            private int nextKey;
            
            /**
             * Sequence缓存值
             */
            private int poolSize;
            
            /**
             * Sequence的名称
             */
            private String keyName;
            
            /**
             * 更新存放Sequence表的语句
             */
            private static final String sql_update = "UPDATE intpub_Sequence SET KEYVALUE = KEYVALUE + ? WHERE KEYNAME = ?";
            
            /**
             * 查询Sequence表中的当前值
             */
            private static final String sql_query = "SELECT KEYVALUE FROM intpub_Sequence WHERE KEYNAME = ?";        public KeyInfo(String keyName, int poolSize) throws SQLException {
                    this.poolSize = poolSize;
                    this.keyName = keyName;
                    retrieveFromDB();
            }        public String getKeyName() {
                    return keyName;
            }        public int getMaxKey() {
                    return maxKey;
            }        public int getMinKey() {
                    return minKey;
            }        public int getPoolSize() {
                    return poolSize;
            }        /**
             * 获取下一个Sequence值
             *
             * @return 下一个Sequence值
             * @throws SQLException
             */
            public synchronized int getNextKey() throws SQLException {
                    if (nextKey > maxKey) {
                            retrieveFromDB();
                    }
                    return nextKey++;
            }        /**
             * 执行Sequence表初始化和更新工作
             *
             * @throws SQLException
             */
            private void retrieveFromDB() throws SQLException {                Connection conn = ConnectionPool.getInstance().getConnection();
                    // 查询数据库
                    PreparedStatement pstmt_query = conn.prepareStatement(sql_query);
                    pstmt_query.setString(1, keyName);
                    ResultSet rs = pstmt_query.executeQuery();
                    if (rs.next()) {
                            maxKey = rs.getInt(1) + poolSize;
                            minKey = maxKey - poolSize + 1;
                            nextKey = minKey;
                            rs.close();
                            pstmt_query.close();
                    } else {
                            String init_sql = "INSERT INTO intpub_Sequence(KEYNAME,KEYVALUE) VALUES('"
                                            + keyName + "',10000 + " + poolSize + ")";
                            Statement stmt = conn.createStatement();
                            stmt.executeUpdate(init_sql);
                            maxKey = 10000 + poolSize;
                            minKey = maxKey - poolSize + 1;
                            nextKey = minKey;
                            stmt.close();
                            return;
                    }                // 更新数据库
                    conn.setAutoCommit(false);
                    PreparedStatement pstmt_up = conn.prepareStatement(sql_update);
                    pstmt_up.setLong(1, poolSize);
                    pstmt_up.setString(2, keyName);
                    pstmt_up.executeUpdate();
                    pstmt_up.close();
                    conn.commit();                rs.close();
                    pstmt_query.close();
                    conn.close();
            }}
      

  2.   


    简单的来说相当于加个计数器,然后用同步来控制下,然后一直getNext...大概如此了,也很少同时请求100W个实例来请求getNext方法,select倒是有机会,所以用上面说的同步控制getNext值还是可以的,不过我觉得应该是项目启动后应该先读取数据库表的最大值,然后赋值给变量里,不可能每次请求都访问数据库获取下一个值...这开销不行
      

  3.   

    自己肯定可以写出来  比如网卡号+时间的毫秒+随机字符串+随机数  这个肯定唯一但是有意义吗?或者说有必要吗?你确定自己写的要优于Sun公司写的?包括时间和空间既然你自己写的没有人家的好  为什么要脱裤子放屁如果什么都自己写  JDK的意义在于何处
      

  4.   

    1 时间+随机字符什么也保证不了。UUID是mac地址+系统时钟,全球同步,那还是mac地址算出来一部分,系统时钟算出来一部分拼一起。2 既然只要效果,那我什么也不做,需要看序列的时候我写个函数把rowid映射成数字给你看。
      

  5.   

    HASH(MAC 地址) +  时间到毫秒
      

  6.   

    对于第一个问题,好多人都说Mac + 毫秒。
    可是Mac真的行嘛?我不清楚我用的 Mac修改器 修改的究竟是不是物理的Mac,但是我修改成和我室友一样的Mac后,我们两个连接路由器时,谁后连接谁上不去网,因为Mac重复!
    对于毫秒数,这个就更坑了:
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.HashSet;
    import java.util.Set;public class TestTimes {
    public static void main(String args[]) { SimpleDateFormat formatter = new SimpleDateFormat(
    "yyyy-MM-dd HH:mm:ss:SSS"); int size = 4000000; long times[] = new long[size];
    for (int i = 0; i < size; i++)
    times[i] = System.currentTimeMillis(); long time = times[0];
    long previousTime = times[0];
    long count = 0; Set<Long> delays = new HashSet<Long>();
    long delay = 0;
    long mindelay = Long.MAX_VALUE;
    long maxdelay = Long.MIN_VALUE;
    for (int i = 0; i < size; i++) {
    if (times[i] > time) {
    delay = time - previousTime;
    delays.add(delay);
    if (delay > 0 && delay < mindelay) {
    mindelay = delay;
    } else if (delay > maxdelay) {
    maxdelay = delay;
    } System.out.print("raw=");
    System.out.print(time);
    System.out.print(" | formatted=");
    System.out.print(formatter.format(new Date(time)));
    System.out.print(" | frequency=");
    System.out.print(count);
    System.out.print(" | delay=");
    System.out.print(delay);
    System.out.println("ms"); previousTime = time;
    time = times[i];
    count = 0;
    } else {
    count++;
    }
    } System.out.println("");
    System.out.println("Minimum delay : " + mindelay + "ms");
    System.out.println("Maximum delay : " + maxdelay + "ms");
    }
    }这是网上直接找的测试代码,我测试了几次,结果惨不忍睹啊:
      

  7.   


    嗯,自己写Sequence挺好!我也写一个试试...
      

  8.   

    以前用过:用户id+'-'+时间+随机字符,正常使用是不会重复,主要是为了区分用户。uuid好用,为什么要自己创造一个。。
      

  9.   

    看错问题了,生成类似uuid的功能偏向底层,实在不懂。。
      

  10.   

    1、oracle序列自增
    2、使用oracle自带SYS_UID()
    3、Java自带的random.getUUID().toSring()
      

  11.   

    天参加复试的时候,技术问的:
     一、
     您有么有一种办法来代替UUID,就是说保证全球无重复!
     Ps:不用说用 时间 + 随机字符,就是这么说的,技术说那也可能有重复的!
     不用说 Base64或Base58,这个也是基于