您好,登錄后才能下訂單哦!
提高mongodb的安全性:
????MongoDB默認沒有密碼,且只允許本地訪問。如果開放外網(wǎng)訪問,就一定要設(shè)置密碼,而且要配置好防火墻,指定只允許哪些ip訪問mongodb端口,否則會有安全隱患。
????配置權(quán)限管理機制:
????????RBAC機制涉及三個關(guān)鍵定義:角色(Roles)、特權(quán)(Privileges)和用戶(Users) 。
????????? 特權(quán)是指一些資源和能夠在資源上進行的操作。
????????? 一個角色可以有多種特權(quán)。
????????? 一個用戶可以有被賦予不同的角色。
????1.創(chuàng)建管理員用戶:
????????在Linux或者macOS中,執(zhí)行命令“mongo”打開MongoDB 命令行客戶端:
????????????
????????????? 第1行代碼:切換到admin數(shù)據(jù)庫。admin數(shù)據(jù)庫是MongoDB自帶的數(shù)據(jù)庫。
????????????? 第3~9行代碼:創(chuàng)建管理員,賬號名稱為admin,密碼為kingnameisgenius ,角色為userAdminAnyDatabase , 控制的數(shù)據(jù)庫為admin
????創(chuàng)建好管理員賬戶以后,在MongoDB命令行客戶端中直接輸入“ exit ”后按回車鍵,即可退出MongoDB 命令行客戶端。
????????修改創(chuàng)建的配置文件mongodb.conf,添加如下兩行內(nèi)容:
????????????security :
????????????????authorization : enabled
????????????
????????保存配置文件并重啟MongoDB數(shù)據(jù)庫。再次執(zhí)行“mongo”命令,發(fā)現(xiàn)雖然能夠連上數(shù)據(jù)庫,但是已經(jīng)不能執(zhí)行常規(guī)操作了
????????????
????????要正常使用命令行客戶端,必需把mongo 的啟動命令修改為:
????????????mongo -u 'admin' -p 'kingnameisgenius' --authenticationDatabase 'admin'
????2.創(chuàng)建普通用戶:
????????管理員賬戶是沒有權(quán)限操作普通數(shù)據(jù)庫的。要操作普通數(shù)據(jù)庫,還需要創(chuàng)建普通用戶。
????????使用管理員賬戶登錄命令行客戶端后,執(zhí)行以下命令創(chuàng)建一個對chapter_8數(shù)據(jù)庫有讀寫權(quán)限,對chapter_4只有讀權(quán)限的普通用戶。
????????????
????3.創(chuàng)建能操作數(shù)據(jù)庫的管理員用戶:
????????管理員(admin賬號)能創(chuàng)建其他用戶, 看似權(quán)限非常大,但它不能訪問任何一個數(shù)據(jù)庫。所以,如果有必要,還需要創(chuàng)建一個能對所有數(shù)據(jù)庫都有全部權(quán)限的用戶。
?????? (1).在MongoDB 的命令行客戶端中,使用管理員C admin )連接MongoDB,然后執(zhí)行以下命令創(chuàng)建一個對所有數(shù)據(jù)庫有完全控制權(quán)限的用戶。
????????????
????????????
????????(2).在可視化連接程序中使用root用戶連接數(shù)據(jù)庫,并把數(shù)據(jù)庫設(shè)定為admin:
????????????????????????????
批量插入與逐條插入的性能對比:
????一條插入語句可能好事幾毫秒,但這過程中網(wǎng)絡傳輸?shù)臅r間占了很大比例。IO(輸入/輸出)操作總是最耗費時間的,無論是硬盤IO還是網(wǎng)絡IO?,F(xiàn)在的寬帶技術(shù),上下行速度動輒每秒幾百兆字節(jié)。如果使用MangoDB插入數(shù)據(jù)還在逐條插入,每一條幾個字節(jié),那可真是白白浪費了網(wǎng)絡帶寬。
????????? 如果寫到本地的MongoDB ,數(shù)據(jù)會在網(wǎng)卡中轉(zhuǎn)一圈再存入硬盤。
????????? 如果寫到遠程的MongoDB ,數(shù)據(jù)會先從本地網(wǎng)卡出去,然后經(jīng)過網(wǎng)線,在電磁波、光信號、電信號之間進行轉(zhuǎn)換,中間通過一層一層的交換機路由器,甚至海底光纜,繞地球一圈再進入目標服務器的網(wǎng)卡最后存入數(shù)據(jù)庫。
????當然,批量插入要考慮多方面:
????????1.(從redis等中)要插入的數(shù)據(jù)量非常大,全部丟到內(nèi)存里超出了內(nèi)存空間咋辦?
????????2.(redis中的)數(shù)據(jù)暫停添加,要過好長一陣才會繼續(xù)添加咋辦?
????????3.假設(shè)redis中有1億數(shù)據(jù),讀到第99999999條數(shù)據(jù)時,突然斷電咋辦?
????????......
????如果Redis中的數(shù)據(jù)是持續(xù)性數(shù)據(jù),則會有新數(shù)據(jù)源源不斷被加入到Redis中,每次添加之間的時間間隔從幾毫秒到幾小時不等。代碼可以如下(python):
????????
????????? 第11行代碼:增加了一個計數(shù)變量,通過第25行代碼實現(xiàn)每獲取一次Redis中的數(shù)據(jù)就讓變量加1。
?????????
第21行代碼:在Redis為空的情況下,如果people_info_list中有數(shù)據(jù),不論有多少數(shù)據(jù),只要請求Redis的次數(shù)為1000的倍數(shù),那么就批量插入數(shù)據(jù)庫。這樣做的好處是,保證people_info_list中的數(shù)據(jù)最多等待100秒就會被插入數(shù)據(jù)庫。這里使用了“%”實現(xiàn)取余操作,“
get_count % 100。”的結(jié)果為get_count除以1000的余數(shù)。如果結(jié)果為0則表示get_count 正好是1000
的整數(shù)倍。
????????? 第24行代碼: 在本次發(fā)現(xiàn)Redis為空的情況下,暫停0.1秒,這樣做可以顯著降低CPU的占用。
插入與更新的性能對比:
????
????(注意:salary字段是字符串,不是整型)
????逐條更新代碼如下(python):
????????
????????
????????? 第7行代碼:讀取所有數(shù)據(jù),并只輸出“_id ”字段(默認輸出〕和“ salary ”字段。
????????? 第8行代碼: 把“ salary ” 字段轉(zhuǎn)換為整型數(shù)據(jù)。
????????? 第10行代碼: 根據(jù)“_id ”宇段把新的“ salary ”字段更新到數(shù)據(jù)庫中。
????????逐條更新19808條數(shù)據(jù)耗時68.7 秒,比逐條插入數(shù)據(jù)的時間還長!!!
????用插入數(shù)據(jù)代替更新數(shù)據(jù):
????????對于必需逐條更新大量數(shù)據(jù)的情況,也可以使用插入代替更新來提高性能。
????????基本邏輯是: 把數(shù)據(jù)插入到另一個集合中, 然后刪除原來的集合,再把新集合改名為原來的集合。
????????
????????? 第6~8行代碼: 初始化兩個連接,分別指向batch集合和update by _insert集合。
????????? 第14行代碼: 把更新以后的數(shù)據(jù)添加到新的列表中。
????????? 第15行: 把新的列表批量插入數(shù)據(jù)庫。
????????更新119808條數(shù)據(jù)并插入新的集合中,耗時3秒。
????????更新完成以后,刪除原來的batch集合,再把新的集合update _by_insert改名為“ batch ”,就變相完成了數(shù)據(jù)的批量更新。
使用索引提高查詢速度:
????在一個集合的數(shù)據(jù)量到達千萬量級以后,查詢速度會變得非常緩慢, 這時就需要使用索引來加快查詢速度。
????索引是一種特殊的數(shù)據(jù)結(jié)構(gòu),它使用了能夠快速遍歷的形式記錄了集合中數(shù)據(jù)的位置。
????如果不使用索引,則每一次查詢數(shù)據(jù)MongoDB都會遍歷整個集合;而如果使用了索引,則MongoDB會直接根據(jù)索引快速找到需要的內(nèi)容。
????????1. 索引的創(chuàng)建
????????????mongodb采用ensureIndex來創(chuàng)建索引,如:
????????????db.user.ensureIndex({"name":1})
????????????表示在user集合的name鍵創(chuàng)建一個索引,這里的1表示索引創(chuàng)建的方向,可以取值為1和-1
????????????在這里面,我們沒有給索引取名字,mongodb會為我們?nèi)∫粋€默認的名字,規(guī)則為keyname1_dir1_keyname2_dir2...keynameN_dirN
????????????keyname表示鍵名,dir表示索引的方向,例如,上面的例子我們創(chuàng)建的索引名字就是name_1
?????????????
????????????索引還可以創(chuàng)建在多個鍵上,也就是聯(lián)合索引,如:
????????????> db.user.ensureIndex({"name":1,"age":1})
????????????這樣就創(chuàng)建了name和age的聯(lián)合索引
????????????除了讓mongodb默認索引的名字外,我們還可以去一個方便記的名字,方法就是為ensureIndex指定name的值,如:
????????????> db.user.ensureIndex({"name":1},{"name":"IX_name"})
????????????這樣,我們創(chuàng)建的索引的名字就叫IX_name了
?????????
????????2. 唯一索引
????????????與RDB類似,我們也可以定義唯一索引,方法就是指定unique鍵位true:
????????????>db.user.ensureIndex({"name":1},{"unique":true})
?????????????
????????3.查看我們建立的索引
????????????索引的信息存在每個數(shù)據(jù)庫的system.indexes集合里面,對這個集合只能有ensureIndex和dropIndexes進行修改,不能手動插入或修改集合。
????????????通過> db.system.indexes.find()可以找到數(shù)據(jù)庫中多有的索引:
????????????> db.system.indexes.find()?
????????????{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.entities", "name" : "_id_" }?
????????????{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.blog", "name" : "_id_" }?
????????????{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.authors", "name" : "_id_" }?
????????????{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.papers", "name" : "_id_" }?
????????????{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.analytics", "name" : "_id_" }?
????????????{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.user", "name" : "_id_" }?
????????????{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.food", "name" : "_id_" }?
????????????{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.user.info", "name" : "_id_" }?
????????????{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "test.userinfo", "name" : "_id_" }?
????????????{ "v" : 1, "key" : { "name" : 1 }, "ns" : "test.user", "name" : "IX_name" }
?????????
????????4.刪除索引
????????????如果索引沒有用了,可以使用dropIndexes將其刪掉:
????????????> db.runCommand({"dropIndexes":"user","index":"IX_name"})?
????????????{ "nIndexesWas" : 2, "ok" : 1 }
????????????ok表示刪除成功
引人Redis ,以降低MongoDB的讀取頻率:
????使用Redis ,以降低MongoDB的查詢頻率, 從而提高新聞爬蟲的爬取效率。
????( 1 )讀取MongoDB 的數(shù)據(jù)并存入Redis 集合中。
????( 2 )使用Redis 集合的“sadd”命令,在判斷數(shù)據(jù)是否存在的同時添加新的數(shù)據(jù)。
????假設(shè), 需要實現(xiàn)一個新聞網(wǎng)站的爬蟲, 讓它會去各個新聞網(wǎng)站爬取新聞, 然后存入MongoDB中。為了不存入重復的新聞,爬蟲需要根據(jù)新聞標題來判斷新聞是否已經(jīng)在數(shù)據(jù)庫中了。
????如果每一條新聞標題去查詢MongoDB 看是否己經(jīng)重復, 這顯然會嚴重影響性能。為了防止頻繁讀MongoDB ,則可以引入Redis 以降低MongoDB 的讀取頻率。
????假設(shè)新聞保存在chapter_8 庫中的news 集合中。一開始news 集合里面已經(jīng)有不少新聞了。
????當爬蟲啟動時,先讀取一次news中的全部新聞標題,并把它們放在Redis中名為news title的集合中。接下來,就不需要讀取MongoDB了。
????爬蟲每爬取到一條新的新聞,就先使用“ sadd ”命令將其添加到Redis的集合中:
????????? 如果返回1,則表示以前沒有這條新聞,將其插入到MongoDB中。
????????? 如果返回0,則表示以前已經(jīng)有這條新聞了,直接丟棄。
????????
????????? 第2行代碼:獲取所有新聞標題。
????????? 第3行代碼:把新聞標題全部添加到Redis中名為news_title的集合中。
????????? 第7行代碼:添加并判斷新聞標題是否己經(jīng)在newstitle集合中。如果己經(jīng)存在,則返回0;如果不存在,則返回1,并將其添加進入Redis集合中。
適當增加冗余信息,提高查詢速度:
????還是以one_by_one中的數(shù)據(jù)為例。假設(shè)定義一個身份"特殊人員"條件是: age小于10, salary大于10000
????如果在插入數(shù)據(jù)庫時就添加一個字段“special_person”,滿足條件就是True,不滿足條件就是False 。那查詢時就簡單了,直接查詢所有special_person字段為True 的數(shù)據(jù)即可
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。