PalDB 線程安全版本

開篇

?本著尊重原創(chuàng)作者精神蚁署,我必須表明這個實現(xiàn)是由組內(nèi)的同事蜂神實現(xiàn)的便脊,我知識站在前人的肩膀上學(xué)習(xí)了下具體的實現(xiàn)!9飧辍哪痰!
?致敬原作者的牛逼技術(shù)K煸!晌杰!

PalDB限制

  • PalDB is optimal in replacing the usage of large in-memory data storage but still use memory (off-heap, yet much less) to do its job. Disabling memory mapping and relying on seeks is possible but is not what PalDB has been optimized for.
  • The size of the index is limited to 2GB. There's no limitation in the data size however.PalDB的索引大小不超過2GB
  • PalDB is not thread-safe at the moment so synchronization should be done externally if multi-threaded.PalDB是不線程安全的

PalDB線程安全代碼實現(xiàn)

?在java的世界里線程安全的實現(xiàn)方法無非是通過鎖或者通過ThreadLocal變量跷睦,加鎖會對性能有一定的損耗,而ThreadLocal相比之下性能損耗幾乎為零乎莉,所以在實現(xiàn)上采用的就是ThreadLocal關(guān)鍵字送讲。

代碼實現(xiàn)比較

?在實現(xiàn)過程中我們把公用的變量都用ThreadLocal修飾,這樣不同的線程讀取數(shù)據(jù)的時候就不會相互干擾惋啃,主要變量由:

  • dataInputOutput 讀取數(shù)據(jù)保存的緩沖區(qū)
  • storage PalDB讀取實現(xiàn)類
  • serialization PalDB自定義實現(xiàn)類的保存變量
//線程不安全版本的ReaderImpl實現(xiàn)類
public final class ReaderImpl implements StoreReader {
  // Configuration
  private final Configuration config;
  // Buffer
  private final DataInputOutput dataInputOutput = new DataInputOutput();
  // Storage
  private final StorageReader storage;
  // Serialization
  private final StorageSerialization serialization;
  // Cache
  private final StorageCache cache;
  // File
  private final File file;
  // Opened?
  private boolean opened;



//線程安全版本的ReaderImpl實現(xiàn)類
public final class ReaderImpl implements StoreReader {
  // Configuration
  private final Configuration config;
  // Buffer
  private final ThreadLocal<DataInputOutput> localDataInputOutput = new ThreadLocal<>();
//  = new DataInputOutput();
  // Storage
  private final ThreadLocal<StorageReader> localStorage = new ThreadLocal<>();
  // Serialization
  private final ThreadLocal<StorageSerialization> localSerialization = new ThreadLocal<>();
  
  private final Map<Thread, StorageReader> allStorageReader = new ConcurrentHashMap<Thread, StorageReader>();

線程不安全版本

?多線程并發(fā)讀取的時候會因為共同了storage造成讀取數(shù)據(jù)混亂哼鬓,所以線程安全版本就需要在這幾個會造成混亂的變量上做文章。包括:

  • dataInputOutput 讀取數(shù)據(jù)保存的緩沖區(qū)
  • storage PalDB讀取實現(xiàn)類
  • serialization PalDB自定義實現(xiàn)類的保存變量
public <K> K get(Object key, K defaultValue) {
    checkOpen();
    if (key == null) {
      throw new NullPointerException("The key can't be null");
    }
    K value = cache.get(key);
    if (value == null) {
      try {
        byte[] valueBytes = storage.get(serialization.serializeKey(key));
        if (valueBytes != null) {

          Object v = serialization.deserialize(dataInputOutput.reset(valueBytes));
          cache.put(key, v);
          return (K) v;
        } else {
          return defaultValue;
        }
      } catch (Exception ex) {
        throw new RuntimeException(ex);
      }
    } else if (value == StorageCache.NULL_VALUE) {
      return null;
    }
    return value;
  }

線程安全版本

?每次都從本線程的ThreadLocal變量中獲取StorageReader讀取數(shù)據(jù)边灭,然后反序列化到ThreadLocal變量中保存的localDataInputOutput存儲序列化的數(shù)據(jù)异希。保證了變量線程的安全。

public <K> K get(Object key, K defaultValue) {
    checkOpen();
    if (key == null) {
      throw new NullPointerException("The key can't be null");
    }
    K value = cache.get(key);
    if (value == null) {
      try {
        byte[] valueBytes = localStorage.get().get(localSerialization.get().serializeKey(key));
        if (valueBytes != null) {

          Object v = localSerialization.get().deserialize(localDataInputOutput.get().reset(valueBytes));
          cache.put(key, v);
          return (K) v;
        } else {
          return defaultValue;
        }
      } catch (Exception ex) {
        throw new RuntimeException(ex);
      }
    } else if (value == StorageCache.NULL_VALUE) {
      return null;
    }
    return value;
  }

代碼實現(xiàn)核心

?在PalDB的api當(dāng)中所有的get/put動作都會有checkOpen方法調(diào)用绒瘦,所以在這個方法內(nèi)部我們把線程不安全的變量都進(jìn)行了拷貝并保存到ThreadLocal當(dāng)中称簿,這是整個實現(xiàn)的核心精華!6杳薄憨降!感謝原作者牛逼的設(shè)計!8眯铩授药!

private void checkOpen() {
    if (!opened) {
      throw new IllegalStateException("The store is closed");
    }
    StorageReader storage = localStorage.get();
    if (null == storage || storage.isClosed()) {
        storage = mainStorage.duplicate();
        localStorage.set(storage);
        allStorageReader.put(Thread.currentThread(), storage);
    } 
    if (null == localDataInputOutput.get()) {
        localDataInputOutput.set(new DataInputOutput());
    }
    if (null == localSerialization.get()) {
        localSerialization.set(new StorageSerialization(this.config));
    }
  }


github倉庫

線程安全PalDB github倉庫

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市呜魄,隨后出現(xiàn)的幾起案子悔叽,更是在濱河造成了極大的恐慌,老刑警劉巖爵嗅,帶你破解...
    沈念sama閱讀 222,104評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娇澎,死亡現(xiàn)場離奇詭異,居然都是意外死亡睹晒,警方通過查閱死者的電腦和手機趟庄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來册招,“玉大人岔激,你說我怎么就攤上這事∈顷” “怎么了?”我有些...
    開封第一講書人閱讀 168,697評論 0 360
  • 文/不壞的土叔 我叫張陵辱匿,是天一觀的道長键痛。 經(jīng)常有香客問我炫彩,道長,這世上最難降的妖魔是什么絮短? 我笑而不...
    開封第一講書人閱讀 59,836評論 1 298
  • 正文 為了忘掉前任江兢,我火速辦了婚禮,結(jié)果婚禮上丁频,老公的妹妹穿的比我還像新娘杉允。我一直安慰自己,他們只是感情好席里,可當(dāng)我...
    茶點故事閱讀 68,851評論 6 397
  • 文/花漫 我一把揭開白布叔磷。 她就那樣靜靜地躺著,像睡著了一般奖磁。 火紅的嫁衣襯著肌膚如雪改基。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,441評論 1 310
  • 那天咖为,我揣著相機與錄音秕狰,去河邊找鬼。 笑死躁染,一個胖子當(dāng)著我的面吹牛鸣哀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播吞彤,決...
    沈念sama閱讀 40,992評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼我衬,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了备畦?” 一聲冷哼從身側(cè)響起低飒,我...
    開封第一講書人閱讀 39,899評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎懂盐,沒想到半個月后褥赊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡莉恼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,529評論 3 341
  • 正文 我和宋清朗相戀三年拌喉,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片俐银。...
    茶點故事閱讀 40,664評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡尿背,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捶惜,到底是詐尸還是另有隱情田藐,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站汽久,受9級特大地震影響鹤竭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜景醇,卻給世界環(huán)境...
    茶點故事閱讀 42,025評論 3 334
  • 文/蒙蒙 一臀稚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧三痰,春花似錦吧寺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至舷丹,卻和暖如春抒钱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背颜凯。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評論 1 272
  • 我被黑心中介騙來泰國打工谋币, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人症概。 一個月前我還...
    沈念sama閱讀 49,081評論 3 377
  • 正文 我出身青樓蕾额,卻偏偏與公主長得像,于是被迫代替她去往敵國和親彼城。 傳聞我的和親對象是個殘疾皇子诅蝶,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,675評論 2 359

推薦閱讀更多精彩內(nèi)容