<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    小明思考

    Just a software engineer
    posts - 124, comments - 36, trackbacks - 0, articles - 0
      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

    所謂snapshot就是一個快照,我們可以從快照中讀到舊的數據。

    先寫一個測試程序來看看snapshot的使用:

    #include <iostream>
    #include 
    "leveldb/db.h"

    using namespace std;
    using namespace leveldb;


    int main() {
        DB 
    *db ;
        Options op;
        op.create_if_missing 
    = true;
        Status s 
    = DB::Open(op,"/tmp/testdb",&db);

        
    if(s.ok()){
            cout 
    << "create successfully" << endl;
            s 
    = db->Put(WriteOptions(),"abcd","1234");
            
    if(s.ok()){
                cout 
    << "put successfully" << endl;
                
    string value;
                s 
    = db->Get(ReadOptions(),"abcd",&value);
                
    if(s.ok()){
                    cout 
    << "get successfully,value:" << value << endl;
                }
            }
            
    if(s.ok()){
                
    string value;
                
    const Snapshot * ss =db->GetSnapshot();
                ReadOptions rop;
                db
    ->Put(WriteOptions(),"abcd","123456");
                db
    ->Get(rop,"abcd",&value);
                
    if(s.ok()){
                        cout 
    << "get successfully,value:" << value << endl;
                }
                rop.snapshot 
    = ss;
                db
    ->Get(rop,"abcd",&value);
                
    if(s.ok()){
                        cout 
    << "get from snapshot successfully,value:" << value << endl;
                }
                db
    ->ReleaseSnapshot(ss);
            }
        }
        delete db;
        
    return 0;
    }

    程序運行的輸出結果是:
    create successfully
    put successfully
    get successfully,value:1234
    get successfully,value:123456
    get from snapshot successfully,value:1234

    可以看出,即使在數據更新后,我們仍然可以從snapshot中讀到舊的數據。

    下面我們來分析leveldb中snapshot的實現。

    SequenceNumber(db/dbformat.h)
    SequenceNumber是leveldb很重要的東西,每次對數據庫進行更新操作,都會生成一個新的SequenceNumber,64bits,其中高8位為0,可以跟key的類型(8bits)進行合并成64bits。
    typedef uint64_t SequenceNumber;

    // We leave eight bits empty at the bottom so a type and sequence#
    // can be packed together into 64-bits.
    static const SequenceNumber kMaxSequenceNumber =
        ((0x1ull << 56) - 1);

    SnapShot(db/snapshot.h),,可以看出snapshot其實就是一個sequence number
    class SnapshotImpl : public Snapshot {
     
    public:
      
    //創建后保持不變
      SequenceNumber number_;  

     
    private:
      friend 
    class SnapshotList; 

      
    //雙向循環鏈表
      SnapshotImpl* prev_;
      SnapshotImpl
    * next_;

      SnapshotList
    * list_;                 // just for sanity checks
    };

    創建snapshot:
    const Snapshot* DBImpl::GetSnapshot() {
      MutexLock l(
    &mutex_);
      
    return snapshots_.New(versions_->LastSequence());
    }

    刪除snapshot:
    void DBImpl::ReleaseSnapshot(const Snapshot* s) {
      MutexLock l(
    &mutex_);
      snapshots_.Delete(reinterpret_cast
    <const SnapshotImpl*>(s));
    }




    posted @ 2012-03-13 16:54 小明 閱讀(4485) | 評論 (0)編輯 收藏

         摘要: leveldb使用SSTable格式來保存數據。格式為:(當前沒有META BLOCK)SSTABLE = |DATA BLOCK1|DATA BLOCK2|...|DATA BLOCK N|META BLOCK1|...|META BLOCK N|META INDEX BLOCK|DATA INDEX BLOCK|Footer|DATA BLOCK = |KeyValues|Restart ar...  閱讀全文

    posted @ 2012-03-12 18:21 小明 閱讀(3870) | 評論 (1)編輯 收藏

         摘要: leveldb在每次數據庫操作之前都會把操作記錄下來。 主要實現在db\log_format.h,db\log_reader.h,db\log_reader.cc,db\log_write.h,db\log_write.cc中。我們來具體看看實現。 日志格式 db\log_format.h log是分塊的,每塊為32K,每條記錄的記錄頭為7個字節,前四個為CRC,然后是長度(2個字節)...  閱讀全文

    posted @ 2012-03-09 16:00 小明 閱讀(3642) | 評論 (1)編輯 收藏

         摘要: 對于一個db來說,存儲是至關重要的問題。運行上一篇的測試程序后,會發現leveldb會生成以下文件:SST文件:數據文件 -- sstable格式*.log: 數據庫日志文件 -- 順序記錄所有數據庫操作,用來恢復數據CURRENT: 文本文件,表明當面的manifest文件LOCK:空文件,數據庫鎖,防止多進程訪問LOG: 日志文件,文本格式LOG.old:上一次的日志文件MANIFEST: 數...  閱讀全文

    posted @ 2012-03-09 11:44 小明 閱讀(2973) | 評論 (1)編輯 收藏

    leveldb是 google對bigtable的一個簡化版的開源實現,很有研究價值。

    我的編譯環境:ubuntu 32&g++ 4.6

    1.安裝git并下載代碼

    sudo apt-get install git-core
    git clone https:
    //code.google.com/p/leveldb/

    2. 編譯leveldb

    cd leveldb
    .
    /build_detect_platform
    make

    為了能夠調試,修改Makefile為debug mode(B模式)
    OPT ?= -g2

    編譯后會生成庫文件:libleveldb.a

    3. 編寫測試程序
    ldbtest.cpp
    #include <iostream>
    #include 
    "leveldb/db.h"

    using namespace std;
    using namespace leveldb;

    int main() {
        DB 
    *db ;
        Options op;
        op.create_if_missing 
    = true;
        Status s 
    = DB::Open(op,"/tmp/testdb",&db);

        
    if(s.ok()){
            cout 
    << "create successfully" << endl;
            s 
    = db->Put(WriteOptions(),"abcd","1234");
            
    if(s.ok()){
                cout 
    << "put successfully" << endl;
                
    string value;
                s 
    = db->Get(ReadOptions(),"abcd",&value);
                
    if(s.ok()){
                    cout 
    << "get successfully,value:" << value << endl;
                }
                
    else{
                    cout 
    << "get failed" << endl;
                }
            }
            
    else{
                cout 
    << "put failed" << endl;
            }
        }
        
    else{
            cout 
    << "create failed" << endl;
        }
        delete db;
        
    return 0;
    }
    注意link的時候需要加上-lpthread.

    運行后得到結果:(Eclipse中運行)

    posted @ 2012-03-08 11:44 小明 閱讀(4832) | 評論 (1)編輯 收藏

         摘要: 和Amazon EC2提供了一系列的命令行工具幫助使用自動化任務,比如創建instance,啟動instance等等。步驟:1. 下載:http://developer.amazonwebservices.com/connect/entry.jspa?externalID=3512. 創建一個腳本用于設置環境變量。windows平臺:Code highlighting produced by Ac...  閱讀全文

    posted @ 2012-03-07 16:03 小明 閱讀(1410) | 評論 (0)編輯 收藏

    學習軟件有三個境界,第一個境界是會使用它,第二個境界是懂得背后的原理,明白它的架構體系,第三個境界學習他的所長,為我所用。研究HBase/BigTable架構和源碼一段時間后,我總結了一些東西可以供我們在設計分布式系統借鑒使用。

    1. 使用可信任的分布式組件來搭建自己的分布式系統。
    設 計一個可靠,健壯的分布式系統是比較困難的。我們知道,為了防止SPOF(Single Point Of Failure)問題,我們要分散風險,把數據放在多個nodes上面去,但是這樣帶來了是數據的同步問題和版本問題,解決這個問題需要運用復雜的 Paxos協議,系統的復雜度自然就升高了。另外一個需要解決的問題是分布式鎖和事件通知機制,以及全局信息共享,設計這些都需要大量的精力和仔細的研 究。

    HBase就不用考慮這些問題,它把數據的同步和冗余問題交給了Hadoop,把鎖機制和全局共享交給了Zookeeper,這大大簡化了HBase的設計。

    所以我們設計系統的時候,也要盡量利用這些可靠,穩定的組件。目前比較流行和穩定的有:
    分布式文件系統 - HDFS
    分布式鎖和目錄 - Zookeeper
    緩存 - MemCached
    消息隊列 - ActiveMQ

    2.避免單點問題(SPOF)
    設計分布式系統要時刻考慮到失敗,不單是軟件可能失敗,硬件也可能掛掉,所以我們系統里面就不能有不可替代的角色。

    HBase 使用Master Server來監控所有的Region Server,一旦其中的一臺出現問題,在其上的Region將會被轉移到其他的Region Server,避免了服務中斷。而Master Server也可以多臺備選,一臺掛掉之后,其他的備胎則會”繼承遺志“,從而讓整個系統得以生存。

    那 HBase如何做到這個呢,一個是使用”心跳機制”,即Region Server要主動定期向Master匯報狀況,另外一個是利用zookeeper里面的”生命節點“,每個server在啟動后要在ZK里面注冊,一旦 這個server掛掉,它在ZK里面的節點就會消失,監聽這個節點的server就會得到通知。

    3.利用不變性提高系統的吞吐量
    我們知道,很多進程/線程修改同一個東西的時候,我們就需要鎖機制來避免沖突。但是鎖帶來的問題是系統性能下降。如果對于一個只讀的對象,就不需要鎖了。

    HBase 在設計存儲的時候考慮到這一點,最新的數據是放在memory里面,以提高性能。但是memory是有限的,我們不可能讓數據一直放在memory里面, 所以我們需要定時把這些數據寫到HDFS/磁盤上面。一種設計是寫到一個可修改的大文件中去,這樣對這個文件的讀寫就需要加鎖了。HBase是每次都寫到 一個新的文件中,一旦文件創建后,這個文件將不能被修改,就是所謂的create-one-read-many。當然這樣也有一個問題,就是時間長了,會 有很多的小文件,每次查找,需要查找這所有的文件,降低了系統的性能,HBase會定時的合并這些小文件生成一個大文件。

    4.利用索引塊提高文件的查詢速度
    HBase的存儲文件(HFile)是用來存儲很多排序后的Key-Value的,如何設計一種支持快速隨機查詢和壓縮的文件是一個有意思的話題。

    HFile 在文件的尾部增加了索引塊,但是不可能對任何一個rowkey都做索引,這樣的話索引塊會很大,而且也不利于壓縮。HFile的做法是定義一個Data Block的大小,這樣就把數據劃分了一個一個的Block,索引只針對這些block做,Block是可以被壓縮的。當查詢一個rowkey的時候,如 果沒有cache的話,首先使用二分法定位到具體的block,然后再解壓,遍歷查詢具體的key。

    HFile這樣的設計兼顧了速度和文件大小的平衡。

    5.自定義RPC機制提供更大的靈活性
    HBase/Hadoop 都沒有利用標準的Java遠程調用規范RMI,而是自己搞了一套。這樣做的好處有幾點,一是減少網絡流量,我們知道,java RMI使用了java serlizable來傳遞參數,java序列化有很多無關的類信息,都占用不少的空間,而且這會帶來對java版本的依賴。二是帶來更大的靈活性,你可 以在其中加入版本檢查,權限認證等。

    那 HBase是怎么設計這個RPC呢?首先它定義了一個writable接口,來代替java序列化,實現這個接口就等于告訴HBase,怎么把這個對象寫 到RPC流中去。使用RPC的時候,需要先寫一個服務器端和客戶端共用的interface,這個interface必須繼承 VersionedProtocol來處理版本問題 。HBase利用Java的動態反射機制(Proxy.newProxyInstance)來生成代 理對象,這樣當Client調用代理對象的時候,Client就會把參數打包,發送到服務器端,然后等待返回結果。服務器會根據interface查找到 具體的實現的對象,調用該對象的方法來執行遠程調用。詳細的做法可以參考HBase/Hadoop的源碼。

    6.內嵌Web Server增強系統的透明度
    當一個后臺進程啟動之后,我們如何了解這個進程的內部狀態呢?傳統方法是通過進程管理器或者Debug log來看進程的情況,但是這些信息很有限。

    HBase利用jetty在進程內部啟動了一個web server,就可以即時的顯示一些系統內部的信息,非常的方便。

    利 用Jetty支持jsp非常的容易,下面是一個示例的代碼。注意的是,需要把jasper-runtime-5.5.12.jar,jasper- compiler-5.5.12.jar,jasper-compiler-jdt-5.5.12.jar,jsp-2.1.jar,jsp-api- 2.1.jar等jar包放在classpath里面,否則會出現頁面解析錯誤。

    server = new Server(port);

    server.setSendServerVersion(false);
    server.setSendDateHeader(false);
    server.setStopAtShutdown(true);

    WebAppContext wac = new WebAppContext();
    wac.setContextPath("/");
    wac.setWar("./webapps/job");
    server.setHandler(wac);
    server.setStopAtShutdown(true);

    posted @ 2012-03-07 10:42 小明 閱讀(2061) | 評論 (0)編輯 收藏

    最近開發了一個開源項目peachbox,主要用于監控android上應用程序的行為,目前可以記錄發短信,刪短信,裝應用程序和卸載程序,以及 某些針對Android 的ROOT行為。

    項目地址: http://code.google.com/p/peachbox

    實現的原理主要是修改Android的源碼,增加一些Hook點,然后就可以記錄行為。

    下載地址:http://peachbox.googlecode.com/files/peachbox.zip

    posted @ 2012-03-02 14:10 小明 閱讀(1909) | 評論 (0)編輯 收藏

    Mysql 的latin1 不等于標準的latin1(iso-8859-1) 和cp1252,比iso-8859-1多了0x80-0x9f字符,比cp1252多了0x81,0x8d,0x8f,0x90,0x9d 一共5個字符。

     

    http://dev.mysql.com/doc/refman/5.0/en/charset-we-sets.html

    latin1 is the default character set. MySQL's latin1 is the same as the Windows cp1252 character set. This means it is the same as the official ISO 8859-1 or IANA (Internet Assigned Numbers Authority) latin1, except that IANA latin1 treats the code points between 0x80 and 0x9f as “undefined,” whereas cp1252, and therefore MySQL's latin1, assign characters for those positions. For example, 0x80 is the Euro sign. For the “undefined” entries in cp1252, MySQL translates 0x81 to Unicode 0x0081, 0x8d to 0x008d, 0x8f to 0x008f, 0x90 to 0x0090, and 0x9d to 0x009d.

    這樣在Java中,如果使用標準的iso-8859-1或者cp1252解碼可能出現亂碼。
    s.getBytes("iso-8859-1") 或者 s.getBytes("cp1252");

    寫了一段代碼來解決這個問題
    private String convertCharset(String s){
            
    if(s!=null){
                
    try {
                    
    int length = s.length();
                    
    byte[] buffer = new byte[length];
                    
    //0x81 to Unicode 0x0081, 0x8d to 0x008d, 0x8f to 0x008f, 0x90 to 0x0090, and 0x9d to 0x009d.
                    for(int i=0;i<length;++i){
                        
    char c = s.charAt(i);
                        
    if(c==0x0081){
                            buffer[i]
    =(byte)0x81;
                        }
                        
    else if(c==0x008d){
                            buffer[i]
    =(byte)0x8d;
                        }
                        
    else if(c==0x008f){
                            buffer[i]
    =(byte)0x8f;
                        }
                        
    else if(c==0x0090){
                            buffer[i]
    =(byte)0x90;
                        }
                        
    else if(c==0x009d){
                            buffer[i]
    =(byte)0x9d;
                        }
                        
    else{
                            buffer[i] 
    = Character.toString(c).getBytes("cp1252")[0];
                        }
                    }
                    String result 
    = new String(buffer,"utf-8");
                    
    return result;
                } 
    catch (UnsupportedEncodingException e) {
                    logger.error(
    "charset convert error", e);
                }
            }
            
    return null;
        }

    posted @ 2012-02-24 14:54 小明 閱讀(1532) | 評論 (0)編輯 收藏

         摘要: 如何在Java中實現Javascript插件?  閱讀全文

    posted @ 2012-01-20 15:27 小明 閱讀(1977) | 評論 (2)編輯 收藏

    僅列出標題
    共5頁: 上一頁 1 2 3 4 5 下一頁 
    主站蜘蛛池模板: 亚洲AV一宅男色影视| 亚洲第一页日韩专区| 亚洲成a人片在线观看中文动漫| 一级人做人爰a全过程免费视频 | 91免费人成网站在线观看18| 久久国产精品亚洲一区二区| 久久国产乱子伦精品免费强| 亚洲高清国产AV拍精品青青草原| 美女被cao网站免费看在线看| 亚洲国产精品无码中文字| 免费91麻豆精品国产自产在线观看| 亚洲Av综合色区无码专区桃色| 免费一区二区三区| 亚洲黄色网址在线观看| 丁香花免费高清视频完整版| 亚洲视频无码高清在线| 免费无遮挡无码视频网站| 边摸边脱吃奶边高潮视频免费| 国产午夜亚洲不卡| 久久九九全国免费| 91午夜精品亚洲一区二区三区| 午夜小视频免费观看| 免费人妻精品一区二区三区| 亚洲日韩欧洲乱码AV夜夜摸| 伊人久久免费视频| 亚洲妇女熟BBW| 亚洲美女高清一区二区三区| 日韩成人免费视频| 亚洲偷自精品三十六区| www亚洲精品少妇裸乳一区二区| 两个人日本免费完整版在线观看1| 色拍自拍亚洲综合图区| 夜夜嘿视频免费看| 两个人看的www视频免费完整版| 亚洲乱码一二三四区国产| 国产免费人成在线视频| 九九精品成人免费国产片| 亚洲综合激情五月丁香六月| 亚洲中文无韩国r级电影| 嫖丰满老熟妇AAAA片免费看| a一级毛片免费高清在线|