Freelance projects

Sunday, December 25, 2011

How can universally unique primary keys can be generated in menory without requiring a database or a singleton?


Without enetring in the specifics (you can fully check out the pattern by reading the appropriate chapter), the solution is to generate a 32 digit key, encoded in hexadecimal composed as follows:
1: Unique down to the millisecond. Digits 1-8 are are the hex encoded lower 32 bits of the System.currentTimeMillis() call. 2: Unique across a cluster. Digits 9-16 are the encoded representation of the 32 bit integer of the underlying IP address. 3: Unique down to the object in a JVM. Digits 17-24 are the hex representation of the call to System.identityHashCode(), which is guaranteed to return distinct integers for distinct objects within a JVM. 4: Unique within an object within a millisecond. Finally digits 25-32 represent a random 32 bit integer generated on every method call using the cryptographically strong java.security.SecureRandom class. 


1. (0-7) IPAddress as HEX - 8 bytes
2. (8-19) CurrentTimeMillis() as HEX - Display all 12 bytes
3. (20-23) SecureRandom() as HEX - Keep only 4 significant bytes. Since this is "random" it doesn't really matter how many bytes you keep or eliminate
4. (24-31) System.identityHashCode as Hex - 8 bytes






import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.logging.Logger;

public class UID {

 private static Logger m_log = Logger.getAnonymousLogger();
 private static char separator;
 private static StringBuilder IPAddressSegment;
 private static SecureRandom prng;

 static {
  try {
   // Get IPAddress Segment
   IPAddressSegment = new StringBuilder();
   InetAddress addr = InetAddress.getLocalHost();
   StringBuilder strTemp = new StringBuilder();
   byte[] ipaddr = addr.getAddress();
   for (int i = 0; i < ipaddr.length; i++) {
    Byte b = new Byte(ipaddr[i]);

    strTemp = new StringBuilder(Integer.toHexString(b.intValue() & 0x000000ff));
    while (strTemp.length() < 2) {
     strTemp.insert(0, '0');
    }
    IPAddressSegment.append(strTemp);
   }

   if (separator != '\u0000') {
    IPAddressSegment.append(separator);
   }

   //Get Random Segment Algoritm
   prng = SecureRandom.getInstance("SHA1PRNG");

  } catch (UnknownHostException ex) {
   m_log.severe("Unknown Host Exception Caught: " + ex.getMessage());
  } catch (NoSuchAlgorithmException nsae) {
   m_log.severe("No Such Algorithm Exception Caught: " + nsae.getMessage());
  }
 }

 public static final String getUID() {
  StringBuilder strRetVal = new StringBuilder(IPAddressSegment);
  StringBuilder strTemp = new StringBuilder();

  //Get CurrentTimeMillis() segment
  strTemp = new StringBuilder(Long.toHexString(System.currentTimeMillis()));
  while (strTemp.length() < 12) {
   strTemp.insert(0, '0');
  }
  strRetVal.append(strTemp);
  if (separator != '\u0000') {
   IPAddressSegment.append(separator);
  }

  // Get Random Segment
  strTemp = new StringBuilder(Integer.toHexString(prng.nextInt()));
  while (strTemp.length() < 8) {
   strTemp.insert(0, '0');
  }

  strRetVal.append(strTemp.substring(4));
  if (separator != '\u0000') {
   IPAddressSegment.append(separator);
  }

  //Get IdentityHash() segment
  strTemp = new StringBuilder(Long.toHexString(System.identityHashCode((Object) new UID())));
  while (strTemp.length() < 8) {
   strTemp.insert(0, '0');
  }
  strRetVal.append(strTemp);

  return strRetVal.toString().toUpperCase();
 }

 public static void main(String[] args) throws Exception {
  for (int i = 0; i < 10; i++) {
   long lngStart = System.currentTimeMillis();
   m_log.info(UID.getUID());
   m_log.info("Elapsed time: " + (System.currentTimeMillis() - lngStart));
  }
 }
}


source