1. 程式人生 > 其它 >分散式(5)資料儲存 MongoDB/HBase/Redis比對與使用

分散式(5)資料儲存 MongoDB/HBase/Redis比對與使用

轉載整理自

https://www.cnblogs.com/vajoy/p/5471308.html
https://www.cnblogs.com/RealWorld/p/9209687.html

文章目錄

MongoDB/HBase/Redis應用場景場景

型別適用場景
MongoDB適用於資料讀效能要求高,表結構變化大,資料規模較大、需要聚合查詢的場景
HBase適用於大資料量持久化儲存場景
Redis適用於讀寫要求高,資料量較小並且不需要持久化的場景

也可以考慮使用一些雲上儲存方案來解決一些資料儲存的問題,比如阿里雲的OSS、OTS

MongoDB

開源,無模式的文件型資料庫,開發語言是C++。可用於替代傳統的關係型資料庫或鍵/值儲存方式。

1.特點

1.1 資料格式
在 MongoDB 中,文件是對資料的抽象,它的表現形式就是我們常說的 BSON(Binary JSON )。
BSON 是一個輕量級的二進位制資料格式。MongoDB 能夠使用 BSON,並將 BSON 作為資料的儲存存放在磁碟中。
一個“文件”

{“name":"mengxiangyue","sex":"nan"}

對於文件是有一些限制的:有序、區分大小寫的,所以下面的兩個文件是與上面不同的:

{"sex":"nan","name":"mengxiangyue"}  
{"Name":"mengxiangyue","sex":"nan"}  

另外,對於文件的欄位 MongoDB 有如下的限制:
_id必須存在,如果你插入的文件中沒有該欄位,那麼 MongoDB 會為該文件建立一個ObjectId作為其值。_id的值必須在本集合中是唯一的。

多個文件則組合為一個“集合”。在 MongoDB 中的集合是無模式的,也就是說集合中儲存的文件的結構可以是不同的,比如下面的兩個文件可以同時存入到一個集合中:

{"name":"mengxiangyue"}  
{"Name":"mengxiangyue","sex":"nan"}  

1.2 效能
MongoDB 目前支援的儲存引擎為記憶體對映引擎。當 MongoDB 啟動的時候,會將所有的資料檔案對映到記憶體中,然後作業系統會託管所有的磁碟操作。這種儲存引擎有以下幾種特點:

  • MongoDB 中關於記憶體管理的程式碼非常精簡,畢竟相關的工作已經有作業系統進行託管。
  • MongoDB 伺服器使用的虛擬記憶體將非常巨大,並將超過整個資料檔案的大小。
    另外,MongoDB 提供了全索引支援:包括文件內嵌物件及陣列。Mongo的查詢優化器會分析查詢表示式,並生成一個高效的查詢計劃。通常能夠極大的提高查詢的效率。

1.3 持久化
MongoDB 在1.8版本之後開始支援 journal,就是我們常說的 redo log,用於故障恢復和持久化。
當系統啟動時,MongoDB 會將資料檔案對映到一塊記憶體區域,稱之為Shared view,在不開啟 journal 的系統中,資料直接寫入shared view,然後返回,系統每60s重新整理這塊記憶體到磁碟,這樣,如果斷電或down機,就會丟失很多記憶體中未持久化的資料。
當系統開啟了 journal 功能,系統會再對映一塊記憶體區域供 journal 使用,稱之為 private view,MongoDB 預設每100ms重新整理 privateView 到 journal,也就是說,斷電或宕機,有可能丟失這100ms資料,一般都是可以忍受的,如果不能忍受,那就用程式寫log吧(但開啟journal後使用的虛擬記憶體是之前的兩倍)。
1.4 CAP類別
MongoDB 比較靈活,可以設定成 strong consistent (CP型別)或者 eventual consistent(AP型別)。
預設是 CP 型別

2.java使用

pom.xml

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver</artifactId>
    <version>3.12.8</version>
</dependency>

demo

public class MongoDBJDBC {
    public static void main(String args[]) {
        try {
            /**
            // 連線到MongoDB服務 如果是遠端連線可以替換“localhost”為伺服器所在IP地址
            // ServerAddress()兩個引數分別為 伺服器地址 和 埠
            ServerAddress serverAddress = new ServerAddress("localhost", 27017);
            List<ServerAddress> addrs = new ArrayList<ServerAddress>();
            addrs.add(serverAddress);
 
            // MongoCredential.createScramSha1Credential()三個引數分別為 使用者名稱 資料庫名稱 密碼
            MongoCredential credential = MongoCredential.createScramSha1Credential("username", "databaseName", "password".toCharArray());
            List<MongoCredential> credentials = new ArrayList<MongoCredential>();
            credentials.add(credential);
            // 通過連線認證獲取MongoDB連線
            MongoClient mongoClient = new MongoClient(addrs, credentials);
            **/
            // 連線到 mongodb 服務
            MongoClient mongoClient = new MongoClient("172.22.25.14", 27017);
            // 連線到資料庫
            MongoDatabase mongoDatabase = mongoClient.getDatabase("mycol");
            // 集合建立
            mongoDatabase.createCollection("test");
            // 集合 test 選擇
            MongoCollection<Document> collection = mongoDatabase.getCollection("test");
            // 插入文件
            /**
             * 1. 建立文件 org.bson.Document 引數為key-value的格式
             * 2. 建立文件集合List<Document>
             * 3. 將文件集合插入資料庫集合中 mongoCollection.insertMany(List<Document>)
             * 插入單個文件可以用 mongoCollection.insertOne(Document)
             */
            Document document = new Document("title", "MongoDB").append("description", "database").append("likes", 100).append("by", "Fly");
            List<Document> documents = new ArrayList<Document>();
            documents.add(document);
            collection.insertMany(documents);
            System.out.println("文件插入成功");
             
            // 檢索所有文件
            /**
             * 1. 獲取迭代器FindIterable<Document>
             * 2. 獲取遊標MongoCursor<Document>
             * 3. 通過遊標遍歷檢索出的文件集合
             */
            FindIterable<Document> findIterable = collection.find();
            MongoCursor<Document> mongoCursor = findIterable.iterator();
            while (mongoCursor.hasNext()) {
                System.out.println(mongoCursor.next());
            }
 
            // 更新文件 將文件中likes=100的文件修改為likes=200
            collection.updateMany(Filters.eq("likes", 100), new Document("$set", new Document("likes", 200)));
 
            // 刪除符合條件的第一個文件
            collection.deleteOne(Filters.eq("likes", 200));
            // 刪除所有符合條件的文件
            collection.deleteMany(Filters.eq("likes", 200));
        }
        catch (Exception e) {
            System.err.println(e.getClass().getName() + ": " + e.getMessage());
        }
    }
}

3.優缺點

優勢

  1. 強大的自動化shading功能,可以快速實現資料複製和節點伸縮
  2. 快速的查詢,MongoDB支援二維空間索引,比如管道,因此可以快速及精確的從指定位置
    獲取資料。MongoDB在啟動後會將資料庫中的資料以檔案對映的方式載入到記憶體中。如果記憶體資源充足的話,這將極大地提高資料庫的查詢速度。
  3. 非結構化資料的爆發增長,增加列在有些情況下可能鎖定整個資料庫,或者增加負載從而
    導致效能下降,由於MongoDB的弱資料結構模式,新增1個新欄位不會對舊錶格有任何影響, 整個過程會非常快速。
  4. 支援動態查詢,查詢指令也使用JSON形式的標記,可輕易查詢文件中內嵌的物件及陣列。

缺點

  1. 單個文件大小限制為16M,32位系統上,不支援大於2.5G的資料;
  2. 對記憶體要求比較大,至少要保證熱資料(索引,資料及系統其它開銷)都能裝進記憶體;
  3. 非事務機制,無法保證事件的原子性。

適用場景

  1. 適用於實時的插入、更新與查詢的需求,並具備應用程式實時資料儲存所需的複製及高度伸縮性。
  2. 非常適合文件化(json)格式的儲存及查詢。
  3. 高伸縮性的場景。
  4. 對效能的關注超過對功能的要求。

HBase

HBase 是 Apache Hadoop 中的一個子專案,屬於 bigtable 的開源版本,所實現的語言為Java(故依賴 Java SDK)。HBase 依託於 Hadoop 的 HDFS(分散式檔案系統)作為最基本儲存基礎單元。
HBase在列上實現了 BigTable 論文提到的壓縮演算法、記憶體操作和布隆過濾器。HBase的表能夠作為 MapReduce 任務的輸入和輸出,可以通過Java API來訪問資料,也可以通過REST、Avro或者Thrift的API來訪問。

1. 特點

1.1 資料格式
HBash 的資料儲存是基於列(ColumnFamily)的,且非常鬆散—— 不同於傳統的關係型資料庫(RDBMS),HBase 允許表下某行某列值為空時不做任何儲存(也不佔位),減少了空間佔用也提高了讀效能。
使用關係型資料庫(RDBMS)和 HBase 對比:
⑴ RDBMS方案:

其中Article表格式:

Author表格式:

⑵ 等價的HBase方案:

1.2 效能
HStore儲存是HBase儲存的核心,它由兩部分組成,一部分是MemStore,一部分是StoreFiles。
MemStore 是 Sorted Memory Buffer,使用者寫入的資料首先會放入MemStore,當MemStore滿了以後會Flush成一個StoreFile(底層實現是HFile),當StoreFile檔案數量增長到一定閾值,會觸發Compact合併操作,將多個StoreFiles合併成一個StoreFile,合併過程中會進行版本合併和資料刪除,因此可以看出HBase其實只有增加資料,所有的更新和刪除操作都是在後續的compact過程中進行的,這使得使用者的寫操作只要進入記憶體中就可以立即返回,保證了HBase I/O的高效能。
1.3 資料版本
Hbase 還能直接檢索到往昔版本的資料,這意味著我們更新資料時,舊資料並沒有即時被清除,而是保留著:
Hbase 中通過 row+columns 所指定的一個存貯單元稱為cell。每個 cell都儲存著同一份資料的多個版本——版本通過時間戳來索引。
時間戳的型別是 64位整型。時間戳可以由Hbase(在資料寫入時自動 )賦值,此時時間戳是精確到毫秒的當前系統時間。時間戳也可以由客戶顯式賦值。如果應用程式要避免資料版本衝突,就必須自己生成具有唯一性的時間戳。每個 cell中,不同版本的資料按照時間倒序排序,即最新的資料排在最前面。
為了避免資料存在過多版本造成的的管理 (包括存貯和索引)負擔,Hbase提供了兩種資料版本回收方式。一是儲存資料的最後n個版本,二是儲存最近一段時間內的版本(比如最近七天)。使用者可以針對每個列族進行設定。
1.4 CAP類別
屬於CP型別

2.java使用

HBase的相關操作可參考下表:

pom.xml

<dependency>
   <groupId>org.apache.hbase</groupId>
   <artifactId>hbase-client</artifactId>
   <version>1.3.1</version>
</dependency>
<dependency>
   <groupId>org.apache.hbase</groupId>
   <artifactId>hbase-server</artifactId>
   <version>1.3.1</version>
</dependency>
<dependency>
   <groupId>org.apache.hbase</groupId>
   <artifactId>hbase-common</artifactId>
   <version>1.3.1</version>
</dependency>

code

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import java.io.IOException;

public class ExampleForHbase {
    public static Configuration configuration;
    public static Connection connection;
    public static Admin admin;

    //主函式中的語句請逐句執行,只需刪除其前的//即可,如:執行insertRow時請將其他語句註釋
    public static void main(String[] args)throws IOException{
        //建立一個表,表名為Score,列族為sname,course
        //createTable("Score",new String[]{"sname","course"});

        //在Score表中插入一條資料,其行鍵為95001,sname為Mary(因為sname列族下沒有子列所以第四個引數為空)
        //等價命令:put 'Score','95001','sname','Mary'
        insertRow("Score", "95001", "sname", "", "Mary");
        //在Score表中插入一條資料,其行鍵為95001,course:Math為88(course為列族,Math為course下的子列)
        //等價命令:put 'Score','95001','score:Math','88'
        //insertRow("Score", "95001", "course", "Math", "88");
        //在Score表中插入一條資料,其行鍵為95001,course:English為85(course為列族,English為course下的子列)
        //等價命令:put 'Score','95001','score:English','85'
        //insertRow("Score", "95001", "course", "English", "85");

        //1、刪除Score表中指定列資料,其行鍵為95001,列族為course,列為Math
        //執行這句程式碼前請deleteRow方法的定義中,將刪除指定列資料的程式碼取消註釋註釋,將刪除制定列族的程式碼註釋
        //等價命令:delete 'Score','95001','score:Math'
        //deleteRow("Score", "95001", "course", "Math");

        //2、刪除Score表中指定列族資料,其行鍵為95001,列族為course(95001的Math和English的值都會被刪除)
        //執行這句程式碼前請deleteRow方法的定義中,將刪除指定列資料的程式碼註釋,將刪除制定列族的程式碼取消註釋
        //等價命令:delete 'Score','95001','score'
        //deleteRow("Score", "95001", "course", "");

        //3、刪除Score表中指定行資料,其行鍵為95001
        //執行這句程式碼前請deleteRow方法的定義中,將刪除指定列資料的程式碼註釋,以及將刪除制定列族的程式碼註釋
        //等價命令:deleteall 'Score','95001'
        //deleteRow("Score", "95001", "", "");

        //查詢Score表中,行鍵為95001,列族為course,列為Math的值
        //getData("Score", "95001", "course", "Math");
        //查詢Score表中,行鍵為95001,列族為sname的值(因為sname列族下沒有子列所以第四個引數為空)
        //getData("Score", "95001", "sname", "");

        //刪除Score表
        //deleteTable("Score");
    }

    //建立連線
    public static void init(){
        configuration  = HBaseConfiguration.create();
        configuration.set("hbase.rootdir","hdfs://localhost:9000/hbase");
        try{
            connection = ConnectionFactory.createConnection(configuration);
            admin = connection.getAdmin();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
    //關閉連線
    public static void close(){
        try{
            if(admin != null){
                admin.close();
            }
            if(null != connection){
                connection.close();
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    /**
     * 建表。HBase的表中會有一個系統預設的屬性作為主鍵,主鍵無需自行建立,預設為put命令操作中表名後第一個資料,因此此處無需建立id列
     * @param myTableName 表名
     * @param colFamily 列族名
     * @throws IOException
     */
    public static void createTable(String myTableName,String[] colFamily) throws IOException {

        init();
        TableName tableName = TableName.valueOf(myTableName);

        if(admin.tableExists(tableName)){
            System.out.println("talbe is exists!");
        }else {
            HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName);
            for(String str:colFamily){
                HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str);
                hTableDescriptor.addFamily(hColumnDescriptor);
            }
            admin.createTable(hTableDescriptor);
            System.out.println("create table success");
        }
        close();
    }
    /**
     * 刪除指定表
     * @param tableName 表名
     * @throws IOException
     */
    public static void deleteTable(String tableName) throws IOException {
        init();
        TableName tn = TableName.valueOf(tableName);
        if (admin.tableExists(tn)) {
            admin.disableTable(tn);
            admin.deleteTable(tn);
        }
        close();
    }

    /**
     * 檢視已有表
     * @throws IOException
     */
    public static void listTables() throws IOException {
        init();
        HTableDescriptor hTableDescriptors[] = admin.listTables();
        for(HTableDescriptor hTableDescriptor :hTableDescriptors){
            System.out.println(hTableDescriptor.getNameAsString());
        }
        close();
    }
    /**
     * 向某一行的某一列插入資料
     * @param tableName 表名
     * @param rowKey 行鍵
     * @param colFamily 列族名
     * @param col 列名(如果其列族下沒有子列,此引數可為空)
     * @param val 值
     * @throws IOException
     */
    public static void insertRow(String tableName,String rowKey,String colFamily,String col,String val) throws IOException {
        init();
        Table table = connection.getTable(TableName.valueOf(tableName));
        Put put = new Put(rowKey.getBytes());
        put.addColumn(colFamily.getBytes(), col.getBytes(), val.getBytes());
        table.put(put);
        table.close();
        close();
    }

    /**
     * 刪除資料
     * @param tableName 表名
     * @param rowKey 行鍵
     * @param colFamily 列族名
     * @param col 列名
     * @throws IOException
     */
    public static void deleteRow(String tableName,String rowKey,String colFamily,String col) throws IOException {
        init();
        Table table = connection.getTable(TableName.valueOf(tableName));
        Delete delete = new Delete(rowKey.getBytes());
        //刪除指定列族的所有資料
        //delete.addFamily(colFamily.getBytes());
        //刪除指定列的資料
        //delete.addColumn(colFamily.getBytes(), col.getBytes());

        table.delete(delete);
        table.close();
        close();
    }
    /**
     * 根據行鍵rowkey查詢資料
     * @param tableName 表名
     * @param rowKey 行鍵
     * @param colFamily 列族名
     * @param col 列名
     * @throws IOException
     */
    public static void getData(String tableName,String rowKey,String colFamily,String col)throws  IOException{
        init();
        Table table = connection.getTable(TableName.valueOf(tableName));
        Get get = new Get(rowKey.getBytes());
        get.addColumn(colFamily.getBytes(),col.getBytes());
        Result result = table.get(get);
        showCell(result);
        table.close();
        close();
    }
    /**
     * 格式化輸出
     * @param result
     */
    public static void showCell(Result result){
        Cell[] cells = result.rawCells();
        for(Cell cell:cells){
            System.out.println("RowName:"+new String(CellUtil.cloneRow(cell))+" ");
            System.out.println("Timetamp:"+cell.getTimestamp()+" ");
            System.out.println("column Family:"+new String(CellUtil.cloneFamily(cell))+" ");
            System.out.println("row Name:"+new String(CellUtil.cloneQualifier(cell))+" ");
            System.out.println("value:"+new String(CellUtil.cloneValue(cell))+" ");
        }
    }
}

3.優缺點

優點

  1. 儲存容量大,一個表可以容納上億行,上百萬列。
  2. 可通過版本進行檢索,能搜到所需的歷史版本資料。
  3. 負載高時,可通過簡單的新增機器來實現水平切分擴充套件,跟Hadoop的無縫整合保障了其資料可靠性(HDFS)和海量資料分析的高效能(MapReduce)。
  4. 在第3點的基礎上可有效避免單點故障的發生。

缺點

  1. 基於Java語言實現及Hadoop架構意味著其API更適用於Java專案;
  2. 佔用記憶體很大,且鑑於建立在為批量分析而優化的HDFS上,導致讀取效能不高。
  3. API相比其它 NoSql 的相對笨拙。

適用場景

  • bigtable型別的資料儲存。
  • 對資料有版本查詢需求。
  • 應對超大資料量要求擴充套件簡單的需求。

Redis

Redis 是一個開源的使用ANSI C語言編寫、支援網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。

1.特點

1.1 資料格式
Redis 通常被稱為資料結構伺服器,因為值(value)可以是 字串(String), 雜湊(Hash/Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)五種型別,操作非常方便。比如,如果你在做好友系統,檢視自己的好友關係,如果採用其他的key-value系統,則必須把對應的好友拼接成字串,然後在提取好友時,再把value進行解析,而redis則相對簡單,直接支援list的儲存(採用雙向連結串列或者壓縮連結串列的儲存方式)。
我們來看下這五種資料型別。
⑴ String

  • string 是 Redis 最基本的型別,你可以理解成與 Memcached 一模一樣的型別,一個key對應一個value。
  • string 型別是二進位制安全的。意思是 Redis 的 string 可以包含任何資料。比如 jpg 圖片或者序列化的物件 。
  • string 型別是 Redis 最基本的資料型別,一個鍵最大能儲存512MB。

例項:

redis 127.0.0.1:6379> SET name zfpx
OK
redis 127.0.0.1:6379> GET name"zfpx"

在以上例項中我們使用了 Redis 的 SET 和 GET 命令。鍵為 name,對應的值為"zfpx"。 注意:一個鍵最大能儲存512MB。
⑵ Hash

  • Redis hash 是一個鍵值對集合。
  • Redis hash 是一個 string 型別的 field 和 value 的對映表,hash 特別適合用於儲存物件。

例項:

redis 127.0.0.1:6379> HMSET user:1 username zfpx password 123
OK
redis 127.0.0.1:6379> HGETALL user:11) "username"2) "zfpx"3) "password"4) "123"

以上例項中 hash 資料型別儲存了包含使用者指令碼資訊的使用者物件。 例項中我們使用了 Redis HMSET, HGETALL 命令,user:1 為鍵值。 每個 hash 可以儲存 232 - 1 鍵值對(40多億)。
⑶ List
Redis 列表是簡單的字串列表,按照插入順序排序。你可以新增一個元素導列表的頭部(左邊)或者尾部(右邊)。
例項:

redis 127.0.0.1:6379> lpush name zfpx1
(integer) 1
redis 127.0.0.1:6379> lpush name zfpx2
(integer) 2
redis 127.0.0.1:6379> lpush name zfpx3
(integer) 3
redis 127.0.0.1:6379> lrange name 0 -11) "zfpx3"2) "zfpx2"3) "zfpx1"

列表最多可儲存 232 - 1 元素 (4294967295, 每個列表可儲存40多億)。
⑷ Sets
Redis的Set是string型別的無序集合。 集合是通過雜湊表實現的,所以新增,刪除,查詢的複雜度都是O(1)。
新增一個string元素到 key 對應的 set 集合中,成功返回1,如果元素已經在集合中返回0,key對應的set不存在返回錯誤,指令格式為

sadd key member

例項:

redis 127.0.0.1:6379> sadd school zfpx1
(integer) 1
redis 127.0.0.1:6379> sadd school zfpx1
(integer) 0
redis 127.0.0.1:6379> sadd school zfpx2
(integer) 1
redis 127.0.0.1:6379> sadd school zfpx2
(integer) 0
redis 127.0.0.1:6379> smembers school
1) "zfpx1"2) "zfpx2"

注意:以上例項中 zfpx1 添加了兩次,但根據集合內元素的唯一性,第二次插入的元素將被忽略。 集合中最大的成員數為 232 - 1 (4294967295, 每個集合可儲存40多億個成員)。
⑸ sorted sets/zset
Redis zset 和 set 一樣也是string型別元素的集合,且不允許重複的成員。 不同的是每個元素都會關聯一個double型別的分數。redis正是通過分數來為集合中的成員進行從小到大的排序。
zset的成員是唯一的,但分數(score)卻可以重複。可以通過 zadd 命令(格式如下) 新增元素到集合,若元素在集合中存在則更新對應score

zadd key score member 

例項:

redis 127.0.0.1:6379> zadd school 0 zfpx1
(integer) 1
redis 127.0.0.1:6379> zadd school 2 zfpx2
(integer) 1
redis 127.0.0.1:6379> zadd school 0 zfpx3
(integer) 1
redis 127.0.0.1:6379> zadd school 1 zfpx4
(integer) 0
redis 127.0.0.1:6379> ZRANGEBYSCORE school 0 100
1) "zfpx1"2) "zfpx3"3) "zfpx4"4) "zfpx2"

1.2 效能
Redis資料庫完全在記憶體中,因此處理速度非常快,每秒能執行約11萬集合,每秒約81000+條記錄(測試資料的可參考這篇《Redis千萬級的資料量的效能測試》)。
Redis的資料能確保一致性——所有Redis操作是原子性(Atomicity,意味著操作的不可再分,要麼執行要麼不執行)的,這保證瞭如果兩個客戶端同時訪問的Redis伺服器將獲得更新後的值。
1.3 持久化
通過定時快照(snapshot)和基於語句的追加(AppendOnlyFile,aof)兩種方式,redis可以支援資料持久化——將記憶體中的資料儲存到磁碟上,方便在宕機等突發情況下快速恢復。
1.4 CAP類別
屬於CP型別

2.java使用

redis單機-哨兵-叢集雲伺服器環境搭建、原理說明及springboot2.0的呼叫

3.優缺點

優勢

  1. 非常豐富的資料結構;
  2. Redis提供了事務的功能,可以保證一串 命令的原子性,中間不會被任何操作打斷;
  3. 資料存在記憶體中,讀寫非常的高速,可以達到10w/s的頻率。

缺點

  1. 持久化功能體驗不佳——通過快照方法實現的話,需要每隔一段時間將整個資料庫的資料寫到磁碟上,代價非常高;而aof方法只追蹤變化的資料,類似於mysql的binlog方法,但追加log可能過大,同時所有操作均要重新執行一遍,恢復速度慢;
  2. 由於是記憶體資料庫,所以,單臺機器,儲存的資料量,跟機器本身的記憶體大小。雖然redis本身有key過期策略,但是還是需要提前預估和節約記憶體。如果記憶體增長過快,需要定期刪除資料。

適用場景

  1. 適用於資料變化快且資料庫大小可遇見(適合記憶體容量)的應用程式。