java uuid

在java中產生uuid的方式是使用java.util.UUID。

UUID.randomUUID().toString();

我在測試redis性能時,使用uuid產生測試數據,發現多線程測試redis的rpush接口的時候,性能老是上不去。
查看cpu利用率也不高,網卡流量也不大。就是tps上不去。但是如果用兩臺client去測,又可以達到更高的tps。

後來直接用jstack查看了下堆棧,發現大多數線程停留在:

java.lang.Thread.State: BLOCKED (on object monitor)
        at java.security.SecureRandom.nextBytes(Unknown Source)
        - waiting to lock <0x00000005ffe1c548> (a java.security.SecureRandom)
        at java.util.UUID.randomUUID(Unknown Source)

原來uuid的生成遇到了性能瓶頸。於是我單獨測試了下生成隨機uuid的性能,發現無論是1個線程還是32個線程還是300個線程,它的tps只能到10萬級別。
甚至是線程數越大,tps越低。tps在每個機器上都不一樣,有的機器上測試tps只有5萬。我們就以一臺雙核4G內存的虛擬機爲例:

tps在 140000+

我們看randomUUID方法的javadoc的描述是:
The UUID is generated using a cryptographically strong pseudo random number generator
也就是說uuid使用了一個強隨機數,也也保證了uuid的不重複性。

public static UUID randomUUID() {
        SecureRandom ng=numberGenerator;
        if(ng == null)
            numberGenerator=ng=new SecureRandom();
 
        byte[] randomBytes=new byte[16];
        ng.nextBytes(randomBytes);
        return new UUID(randomBytes);
}

再看SecureRandom的javadoc
Note: Depending on the implementation, the generateSeed and nextBytes methods may block as entropy is being gathered, for example, if they need to read from /dev/random on various unix-like operating systems.

也就是說SecureRandom的nextBytes方法,依賴隨機數的產生,如果隨機數不夠了,它有可能就會堵塞在那邊。 比如隨機數的產生是讀取unix類系統的/dev/random文件。

我們再去看有關/dev/random的信息:

Linux中的隨機數可以從兩個特殊的文件中產生,一個是/dev/urandom.另外一個是/dev/random。他們產生隨機數的原理是利用當前系統的熵池來計算出固定一定數量的隨機比特,然後將這些比特作爲字節流返回。熵池就是當前系統的環境噪音,熵指的是一個系統的混亂程度,系統噪音可以通過很多參數來評估,如內存的使用,文件的使用量,不同類型的進程數量等等。如果當前環境噪音變化的不是很劇烈或者當前環境噪音很小,比如剛開機的時候,而當前需要大量的隨機比特,這時產生的隨機數的隨機效果就不是很好了。

這就是爲什麼會有/dev/urandom和/dev/random這兩種不同的文件,後者在不能產生新的隨機數時會阻塞程序,而前者不會(ublock),當然產生的隨機數效果就不太好了,這對加密解密這樣的應用來說就不是一種很好的選擇。/dev/random會阻塞當前的程序,直到根據熵池產生新的隨機字節之後才返回,所以使用/dev/random比使用/dev/urandom產生大量隨機數的速度要慢。

jdk默認的是讀取/dev/random文件產生強隨機數,但是如果不是爲了產生加密隨機數,我們可以設置jdk讀取/dev/urandom產生隨機數,從而生成隨機uuid。

在java啓動項中增加-Djava.security.egd=file:/dev/./urandom 配置項(不能寫作/dev/urandom,關於這個,網上有相關八卦歷史~)

再去相同的機器上測試uuid的性能:

tps在 720000+

發佈了1165 篇原創文章 · 獲贊 19 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章