常見的NoSQL數(shù)據(jù)庫(Memcache,Redis,MongoDB)

NoSql的含義

NoSQL ,(Not Only SQL),泛指非關系型數(shù)據(jù)庫, 它是由一次叫“反Sql運動”的社區(qū)討論而誕生的體系。這個運動的發(fā)起最早源自于社區(qū)網(wǎng)站 LiveJournal的開發(fā)團隊,它們的初衷是為了用于減少數(shù)據(jù)庫連接數(shù),減輕數(shù)據(jù)庫的工作壓力,但發(fā)展至今有著其他不同的應用領域,因此NoSQL處于一種所謂百家爭鳴的,各執(zhí)一詞的時期。但我們作為NoSql的學習者和應用者,我們不需要關心和糾結這些NoSql的爭論,也不需要參與到這些爭論當中。

只要不是關系型數(shù)據(jù)庫里面的東西,都可以叫做nosql數(shù)據(jù)庫。

NoSql的共同特點和優(yōu)勢

  • NoSQL 通常是以key-value形式存儲的(如:Memcache、Redis、Mongodb)
  • 不支持SQL語句
  • 沒有表結構
  • 配置簡單
  • 靈活、高效的操作與數(shù)據(jù)模型(key-value存儲,一般叫做hash表)
  • 低廉的學習成本
  • 能很好地作為MySql的中間層(cache is king 有緩存肯定會更好、緩存也會引來問題?數(shù)據(jù) 一致性的問題)
  • 能很好地支持PHP

NoSql的共同的缺點

  • 沒有統(tǒng)一的標準
  • 安全性極差(memcache沒有權限系統(tǒng) )
  • 沒有正式的官方支持 (社區(qū)維護)(GitHub)
  • 各種產(chǎn)品還不算成熟
  • 權威支持的產(chǎn)品價格很高(如:阿里云)

NoSql的產(chǎn)品分類


Memcache

  • 端口:11211

  • 純內存存儲,是所有NoSQL產(chǎn)品中最簡單,速度最快的,但也是功能最弱的

  • 內置分布式算法,開發(fā)者不需要自己去實現(xiàn)

    • 使用分布式存儲數(shù)據(jù)
    $mem = new Memcache();
    
    $mem->addServer('127.0.0.1', 11212);
    $mem->addServer('127.0.0.1', 11213);
    $mem->addServer('127.0.0.1', 11214);
    
    # 數(shù)據(jù)自動分布在3臺memcache服務器上,不用開發(fā)人員操心
    for($i = 1; $i < 99; $i++){
        $mem->set('key_' . $i, 'value_' . $i, 0, 86400);
    }
    
    echo "ok";
    
    • 獲取分布式數(shù)據(jù)
    $mem = new Memcache();
      
    $mem->addServer('127.0.0.1', 11212);
    $mem->addServer('127.0.0.1', 11213);
    $mem->addServer('127.0.0.1', 11214);
    
    # 開發(fā)人員無法得知數(shù)據(jù)的來源
    $data = $mem->get('key_1');
    var_dump($data);
    
  • 可以設置數(shù)據(jù)有效期

    Memcache設置緩存的有效期可以使用:

    1. 緩存時間:使用s秒數(shù),但是不能超過86400*30s,也就是30天的秒數(shù)
    2. 時間戳:但是該方式只有在Linux下才可以使用,windows下不生效,使用時間戳可以設置大于30天的有效期
  • 使用Telnet協(xié)議進行傳輸,沒有加密功能,安全性很差,但在內網(wǎng)上影響不大

  • 最大存儲空間只有64M,一旦爆滿,Memcache會指定重啟,并釋放當前所有的內存

  • 存儲形式為KV型,單個Value值最大為1M(單個chunk最大為1M)

  • 數(shù)據(jù)存儲在內存中,一旦服務器維護或重啟,數(shù)據(jù)就會丟失

  • 數(shù)據(jù)零散,無法遍歷,管理數(shù)據(jù)完整性非常一般

  • 存儲的數(shù)據(jù)都是字符串類型

  • 可以配置Session共享(在php.ini中配置session.save_handler = memcache,session.save_path = "tcp://#memcache服務器的IP#:11211")

    ; php.ini
    session.save_handler = memcache
    session.save_path = "tcp://127.0.0.1:11211"
    
  • Memcache的內存分配機制

    ? 由于Memcache是一個內存緩存系統(tǒng),就涉及內存申請和釋放的問題,不斷的申請和釋放內存,會導致內存的碎片化。為了解決內存碎片化的問題,Memcache使用了內存預先分配機制。

    ? Memcache將64M的存儲空間分割成64份,每一份都是1M的空間,這樣的空間稱為slab class

    ? slab class里面的存儲數(shù)據(jù)的單元稱為chunk,最小的chunk默認為96B,最大為1M。

    ? 相鄰slab class之間chunk大小的比值是固定的,這個比值被稱為增長因子,它可以根據(jù)實際的業(yè)務做相應的調整。

  • Memcache內部使用了LRU算法

    ? LRU(Least Recently Used )算法被稱為最近最少使用原則。

    ? 當memcache的一個slab里面的chunk不夠使用的情況下(存儲滿了,數(shù)據(jù)在有效期)當有新的滿足chunk的數(shù)據(jù)過來的情況下,memcache會優(yōu)先把slab里面最近一段時間內,最不活躍的數(shù)據(jù)先剔除掉,騰出空間,給新的數(shù)據(jù)使用。

  • Memcache使用惰性刪除機制

    ? Memcache本身不監(jiān)控數(shù)據(jù)是否過期,當下一次重新獲取數(shù)據(jù)的時候,才會去查看數(shù)據(jù)是否有效,如果有效則返回,否則就清除。

  • Memcache實現(xiàn)高可用

    • sina公司開發(fā)的MemcacheDB
    • repcached:全稱replication cached,是由日本人發(fā)明的memcache的高可用技術,簡稱復制緩沖區(qū)技術。

Redis

  • 端口:6379

  • 默認存在0~15共16個數(shù)據(jù)庫

  • 支持緩存數(shù)據(jù)持久化

  • 支持5種數(shù)據(jù)類型

    • String(字符串)
    • list(鏈表)
    • hash(哈希表)
    • set(無序集合)
    • sorted set(有序集合,縮寫為zset)
  • 高并發(fā)而生

  • Redis使用一致性哈希虛擬節(jié)點算法可以實現(xiàn)分布式功能

  • 存儲形式為KV型,單個Value值最大可以存儲1G的數(shù)據(jù),存儲總量可以視硬盤大小而定

  • Redis可以開啟安全認證

    # redis.conf
    # 由于配置文件中的密碼是明文,所以一般會把該配置文件的權限設置為600
    requirepass ##密碼##(明文)
    
  • Redis的持久化

    • 快照模式

      默認模式,快照文件為dump.rdb。

      當網(wǎng)站的數(shù)據(jù)量變大時,該文件也會隨之增大,操作效率很低。

    • aof模式(append of file)

      aof文件有點類似MySQL的binlog日志(讀寫分離)

      aof文件會把用戶的操作記錄包括查詢的過程全部記錄,當服務器出現(xiàn)問題的時候,Redis會將數(shù)據(jù)從內存中保存到aof文件當中,當服務器重新運行時,Redis就會根據(jù)aof文件中的操作記錄,把數(shù)據(jù)重新還原到內存當中去,以確保數(shù)據(jù)的完整性。

      快照模式和aof模式是完全互斥的。

      如果aof的模式一旦啟動,那么快照就會失效,Redis就會把所有的數(shù)據(jù)緩存到內存當中,如果發(fā)生重啟,停止,關閉服務器等行為,那么aof文件就會把內存中數(shù)據(jù)同步到硬盤中。

      開啟aof模式:

      # redis.conf
      
      appendonly yes
      
      appendfilename "appendonly.aof"
      
      # appendfsync always
      # always 的選項代表Redis的命令每一次只要運行那么就會馬上寫入aof文件當中,該選項是最沒有效率的,然而它卻是最具備操作記錄完整性的。
      
      appendfsync everysec
      # everysec 的選項是Redis比較折中的選項,代表每一秒中只有有操作那么就會進行操作記錄,但是如果在某一秒當中redis發(fā)生故障,那么這一秒的數(shù)據(jù)操作記錄將有可能發(fā)生丟失的情況,存在一定的風險,然而這個配置的性能比較適中,所以建議使用
      
      # appendfsync no
      # no 該配置的效率完全依賴您當前所在使用的操作系統(tǒng)和計算機的性能,如果操作系統(tǒng)穩(wěn)定,計算機的性能強大,那么這一項是最有效率的,反而就是最差,所以一般最好不要設置該項
      

MongoDB

  • 端口:27017

  • 文檔型數(shù)據(jù)庫

  • 存儲的是經(jīng)過特殊處理的json數(shù)據(jù),也叫Bson(json二進制化后的數(shù)據(jù))

  • MongoDB內部使用js解釋引擎來實現(xiàn)數(shù)據(jù)的分析,在插入的時候,將數(shù)據(jù)轉換成二進制的Bson來存儲;在查詢的時候,將數(shù)據(jù)Bson轉換成json對象返回

  • 存在數(shù)據(jù)庫的概念

    # 查看當前所有數(shù)據(jù)庫
    > show dbs;
    
    # 選擇數(shù)據(jù)庫
    > use test;
    
    # 查看當前庫下所有的數(shù)據(jù)表
    > show tables;
    > show conllections;
    
    # 創(chuàng)建數(shù)據(jù)庫
    # MongoDB的數(shù)據(jù)庫是隱式創(chuàng)建,當該數(shù)據(jù)庫下有數(shù)據(jù)之后,它就會被自動創(chuàng)建了
    
    # 刪除當前數(shù)據(jù)庫
    > db.dropDatabase();
    
  • Collection(集合) → 相當于MySQL中的表

    # 創(chuàng)建表
    # 顯式創(chuàng)建
    > db.createConllection('collectionName');
    # 隱式創(chuàng)建
    > db.collectionName.insert(/*json數(shù)據(jù)*/);
    
    # 刪除表
    > db.collectionName.drop();
    
    ####### 查找
    # 查找所有
    > db.collectionName.find();
    
    # 將取出的數(shù)據(jù)以優(yōu)雅的格式顯式,鏈式調用
    > db.collectionName.find().pretty();
    
    # 按條件查找和展示
    > db.collectionName.find({/*查詢條件*/}, {/*要展示的字段*/});
    # 例如:select age, name from stu where age > 18;
    > db.stu.find({'age':{$gt:18}}, {'_id':0, 'age':1, 'name':1});
    
    # 只查詢一條
    # 例如:select age, name from stu where age > 18 limit 1;
    > db.stu.findOne({'age':{$gt:18}}, {'_id':0, 'age':1, 'name':1});
    
  • Document(文檔) → 相當于MySQL表中的記錄

    ####### 增加
    > db.collectionName.insert(/*json數(shù)據(jù)*/);
    # 增加單條記錄
    > db.collectionName.insert({'name':'rico', 'age':19, 'gender':male});
    # 增加多條記錄
    > db.collectionName.insert([
        {'name':'rico', 'age':19, 'gender':male},
        {'name':'nacy', 'age':22, 'gender':female, 'birthday':'1993/01/05'},
        {'name':'zaks', 'age':30, 'gender':male, 'className':'php88'}
    ]);
    
    ####### 刪除
    > db.collectionName.remove(/*查詢表達式*/, /*選項*/);
    # 例如:delete from stu where age < 10;
    > db.stu.remove({'name':{$gt:10}});
    # 例如:delete from stu where age < 10 limit 1;
    > db.stu.remove({'name':{$gt:10}}, {justOne:true});
    
    ####### 修改
    > db.collectionName.update(/*查詢表達式*/, /*新值*/);
    # 例如:update stu set name='coco' where _id=3;
    > db.stu.update({'_id':3}, {'name':'coco'}); # 注意:這里修改之后,文檔中只有'_id'和'name'了
    # 如果只是想修改某列,則可以使用$set
    > db.stu.update({'_id':3}, {$set:{'name':'coco'}}); 
    
    ####### 分頁
    # 例如:select * from stu limit 5, 3;
    > db.stu.find().limit(3).skip(5);
    
    ####### 排序
    # 例如:select * from stu order by age;
    > db.stu.find().sort({'age':1});
    # 例如:select * from stu order by age desc;
    > db.stu.find().sort({'age':-1});
    
  • 怎么關閉 mongoDB?千萬不要 kill -9 pid,可以 kill -2 pid 或 db.shutdownServer()

  • mongodb的權限驗證機制

    http://blog.csdn.net/lk10207160511/article/details/50281883


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容