redis2018-07-02

數據庫(DB)

RDBMS -- MySQL

nosql -- mongodb

redis 典型nosql數據庫

========================================================================

redis ? 安裝:

Linux:

????????redis-stable.tar.gz (源代碼包):

????????tar -zxvf

????????make

????????cd src

????????make install

????????sudo apt-get/apt install redis-server(不推薦)

window:

????????exe:

????????????????????下一步

????????zip:

????????????????1、解壓zip包

????????????????2、將主目錄配置到path

????????????????3、cmd redis-server

????????????????4、cmd redis-cli

?將redis-server注冊為window的服務或者Linux的守護進程

window:

????????redis-server 配置文件的絕對路徑 --service-install

????????net start redis? # 啟動redis服務

????????redis-cli

linux:

????????修改配置文件:137行 daemonize yes 表示以守護進程運行redis

????????redis-service 配置文件的絕對路徑

????????redis-cli

????????redis的配置文件:

redis有五種數據類型:

????????String:

????????hash:

????????list

????????set

????????sorted set? zset

==String類型的操作==

set key value # 表示將key對應的字符串存儲起來

eg:set ? ?name ? ?zhangsan

get key # 獲取key對應的值

eg:get ? ?name

mset key1 v1 key1 v2 key3 v3 # 多個鍵值對保存

eg:mset ? ?age ? ?18 ? ?gender ? ?nan ? ?nickname ? ?xiaozhang ??

mget key1 key2 key3 # 獲取多個key對應的值

eg:mset ? ?name ? ?age ? ?gender ? ?nickname ?

setex key seconds value # 設置一個key,seconds秒后失效

eg:setex ? ?address ? ?10 ? ?zz

incr key # 將key對應的值加一,注意:只能是數字字符串

eg:incr ? ?age

incrby key number # 將key對應的值加number

eg:incrby ? ?age ? ?10

decr key # 將key對應的值減一

eg:decr ? ?age

decrby key number # 將key對應的值減number

eg:decrby ? ?age ? ?5

strlen key # 求key對應的長度

eg:strlen ????name/age/gender/nickname

append key value # 對key的值末尾進行追加

eg:append ? ?nickname ? ?laozhang

setrange key offset value # 將key對應的值的offset位置開始替換為value

eg:setrange ? ?nickname ? ?3 ? ? today

getrange key start end # 獲取key對應的值的區間值

eg:getrange ? ?nickname ? ?0 ? ?-1

getrange ? ?nickname ? ?3 ? ?6

setnx key value # 判斷是否存在key,如果不存在,則增加

eg: ?setnx ? ?name ? ?zhangsan

? ? ? ? ? setnx ? ?name ? ?lisi ?

==key的操作==

keys * # 查詢當前數據庫下的所有key

exists key # 判斷key是否存在

eg:exists ? ?name ? ?

exists ? ?valuex

type key # 判斷key對應的值的類型

eg: ?type ? ? name/age/gender/nickname

del key # 刪除key

eg:del ? ?address


expire key seconds # 為一個存在的key設置失效時間

eg:expire ? ?nickname ? ?50

# set + expire? <====> setex

ttl key(Time To Live) # 查看某個key的失效時間 -1 永久有效 -2 失效 正數表示正在失效的時間秒數

eg: ttl ? ?name

????? ? ttl ? ? address

????????ttl ? ?nickname

persist key # 取消key的失效,讓它永久有效

eg:persist ? ?nickname


select index # 切換數據庫

eg:select ? ?1

move key index # 將當前數據庫的key移動到對應數據庫下

eg:move ? ? nickname ????1

dbsize # 返回當前數據庫下key的數量

Info # 查詢當前數據的信息

flushdb # 清空當前數據庫? (慎用)

flushall # 清空所有的數據庫(慎用)


==hash的操作==

hset key field value # 保存一個對象的屬性和值

eg:hset ? ?u1 ? ?name ? ?zhangsan

hget key field # 通過對象的屬性獲取值

eg:hget ? ?u1 ? ?name

hmset key f1 v1 f2 v2…… # 保存一個對象的多個屬性和值

eg:hmset ? ?u1 ? ?age ? ?18 ? ?gender ? ?nan ? ?nickname ? ?xiaozhang

hmget key f1 f2 # 通過對象的多個屬性獲取值

eg:hmget ? ?u1 ? ?name ? ?age ? ?gender ? ?nickname

hgetall key # 獲取對象的所有屬性和值

eg:hgetall ? ?u1


hkeys key # 獲取對象的所有屬性名稱

eg:hkeys ? ?u1

hvals key # 獲取對象的所有屬性的值

eg:hvals ? ?u1

hlen key # 獲取對象的屬性個數

eg:hlen ? ?u1

hexists key field # 查詢對象是否存在某個屬性

eg:hexists ? ?u1 ? ?name/address

hdel key field # 刪除對象的某個屬性

eg:hdel ? ?u1 ? ?nickname

hstrlen key field # 查詢對象的屬性的值的長度

eg:hstrlen ? ?u1 ? ?age/name.....

==list的操作==

redis的list是一個隊列和棧 字符串 的實現

lpush key value1 value2…… # 從左側壓入數據到list中

eg: ?lpush ? ?list1 ? ?zhangsan

? ? ? ? ? lpush ? ?today ? ? is ? ?good

rpush key value1 value2…… # 從右側壓入數據到list中

eg: ? ?rpush ? ?list1 ? ?lisi ? ?wangwu ? ?zhaoliu

lrange key start end # 從左側start位置開始循環展示數據,到end結束

eg:lrange ? ? list1 ? ?0 ? ? -1

linsert key before|after pivot value: # 在一個元素前/后插入數據

eg: ?linsert ? ?list1 ? ?before ? ?zhangsan ? ? xiaozhang????

? ? ? ? ?linsert ? ?list1 ? ?after ? ?wangwu ? ?xiaowang

lpop key # 移除第一個元素

eg:lpop ? ?list1

rpop key # 移除最后一個元素

eg:rpop ? ?list1

llen key # 獲取list的元素個數

eg:llen ? ? list1

lindex key index # 獲取索引對應的值

eg:lindex ? ? list1 ? ? 3

ltrim key start end # 截取list,從start位置開始,到end結束(組成新的列表,代替原來的)

eg:ltrim ? ?list1 ? ?0 ? ?-1


lrem key count value # 刪除value元素,count個(有重復或者刪一個或0)

eg:lrem ? ?list1 ? ?2 ? ?is

==set的操作==

sadd key value1 value2…… # 將v1,v2……添加到set中

eg:sadd ? ? set1 ? ?today ? ?is ? ?good

????????sadd ? ?set2 ? ?happy ? ?new ? ?year ? ?very ? ?good

smembers key # 展示set中所有元素

eg:smembers ? ?set1

sismember key value # 判斷value在不在key中

eg:sismember ? ?set1 ? ?very

scard key # 返回set的元素個數

eg:scard ? ?set1

sinter key [key]: # 獲取多個集合 交集

eg: ?sinter ? ?set1 ? ?set2

sdiff key [key]: # 獲取多個集合的差集

eg:sdiff ? ?set1 ? ?set2

????????sdiff ? ?set2 ? ?set1

sunion key [key]: # 獲取多個集合的并集

eg:sunion ? ?set1 ? ?set2

srem key member # 移除元素

eg:srem ? ?set1 ? ?good

spop key [count] # 隨機移除元素

eg:spop ? ?set1 ? ?[2]

sdiffstore newkey key1 key2 # 將差集保存成一個新的set

eg:sdiffstore ? ?set3 ? ?set1????set2

srandmember key # 隨機獲取一個元素

eg:srandmember ? ?set1

==zset的操作==

zadd key score value2 [score value2] # 將值添加到zset中

eg:zadd ? ? z1 ? ?13 ? ? liuzhijuan

zrange key start end # 遍歷展示數據

eg:zrange ? ? z1 ? ?0 ? ?-1

zcard key???? # 返回set的元素個數

eg:zcard ? ?z1

zcount ? ?key ? ? min ? ?max????返回score值在min和max之間的數據個數

eg:zcount ? ?z1 ? ?3 ? ?20

zscore ? ?key ? ?value????返回集合中元素的score(權重值)

eg:zscore ? ?z1 ? ?juan


面試題:

緩存:

????緩存的英文是cache,一般是用于RAM存儲器,用于存儲臨時數據,斷電后存儲的內容會消失。緩存是臨時文件交換區,電腦把最常用的文件從存儲器里提出來臨時放在緩存里,就像把工具和材料搬上工作臺一樣,這樣會比用時現去倉庫取更方便。因為緩存往往使用的是RAM(斷電即掉的非永久儲存),所以在忙完后還是會把文件送到硬盤等存儲器里永久存儲。電腦里最大的緩存就是內存條了,最快的是CPU上鑲的L1和L2緩存,顯卡的顯存是給GPU用的緩存,硬盤上也有16M或者32M的緩存。千萬不能把緩存理解成一個東西,它是一種處理方式的統稱。

什么是redis、什么是memcache,兩者有什么區別?

>>Memcached

Memcached的優點:

Memcached可以利用多核優勢,單實例吞吐量極高,可以達到幾十萬QPS(取決于key、value的字節大小以及服務器硬件性能,日常環境中QPS高峰大約在4-6w左右)。適用于最大程度扛量。

支持直接配置為session handle。

Memcached的局限性:

只支持簡單的key/value數據結構,不像Redis可以支持豐富的數據類型。

無法進行持久化,數據不能備份,只能用于緩存使用,且重啟后數據全部丟失。

無法進行數據同步,不能將MC中的數據遷移到其他MC實例中。

Memcached內存分配采用Slab Allocation機制管理內存,value大小分布差異較大時會造成內存利用率降低,并引發低利用率時依然出現踢出等問題。需要用戶注重value設計。

>>Redis

Redis的優點:

支持多種數據結構,如 string(字符串)、 list(雙向鏈表)、dict(hash表)、set(集合)、zset(排序set)、hyperloglog(基數估算)

支持持久化操作,可以進行aof及rdb數據持久化到磁盤,從而進行數據備份或數據恢復等操作,較好的防止數據丟失的手段。

支持通過Replication進行數據復制,通過master-slave機制,可以實時進行數據的同步復制,支持多級復制和增量復制,master-slave機制是Redis進行HA的重要手段。

單線程請求,所有命令串行執行,并發情況下不需要考慮數據一致性問題。

支持pub/sub消息訂閱機制,可以用來進行消息訂閱與通知。

支持簡單的事務需求,但業界使用場景很少,并不成熟。

Redis的局限性:

Redis只能使用單線程,性能受限于CPU性能,故單實例CPU最高才可能達到5-6wQPS每秒(取決于數據結構,數據大小以及服務器硬件性能,日常環境中QPS高峰大約在1-2w左右)。

支持簡單的事務需求,但業界使用場景很少,并不成熟,既是優點也是缺點。

Redis在string類型上會消耗較多內存,可以使用dict(hash表)壓縮存儲以降低內存耗用。

Mc和Redis都是Key-Value類型,不適合在不同數據集之間建立關系,也不適合進行查詢搜索。比如redis的keys pattern這種匹配操作,對redis的性能是災難。

>>mongoDB?

mongoDB?是一種文檔性的數據庫。先解釋一下文檔的數據庫,即可以存放xml、json、bson類型系那個的數據。

這些數據具備自述性(self-describing),呈現分層的樹狀數據結構。redis可以用hash存放簡單關系型數據。

mongoDB?存放json格式數據。

適合場景:事件記錄、內容管理或者博客平臺,比如評論系統。

1.mongodb持久化原理

mongodb與mysql不同,mysql的每一次更新操作都會直接寫入硬盤,但是mongo不會,做為內存型數據庫,數據操作會先寫入內存,然后再會持久化到硬盤中去,那么mongo是如何持久化的呢

mongodb在啟動時,專門初始化一個線程不斷循環(除非應用crash掉),用于在一定時間周期內來從defer隊列中獲取要持久化的數據并寫入到磁盤的journal(日志)和mongofile(數據)處,當然因為它不是在用戶添加記錄時就寫到磁盤上,所以按mongodb開發者說,它不會造成性能上的損耗,因為看過代碼發現,當進行CUD操作時,記錄(Record類型)都被放入到defer隊列中以供延時批量(groupcommit)提交寫入,但相信其中時間周期參數是個要認真考量的參數,系統為90毫秒,如果該值更低的話,可能會造成頻繁磁盤操作,過高又會造成系統宕機時數據丟失過。

2.什么是NoSQL數據庫?NoSQL和RDBMS有什么區別?在哪些情況下使用和不使用NoSQL數據庫?

NoSQL是非關系型數據庫,NoSQL = Not Only SQL。

關系型數據庫采用的結構化的數據,NoSQL采用的是鍵值對的方式存儲數據。

在處理非結構化/半結構化的大數據時;在水平方向上進行擴展時;隨時應對動態增加的數據項時可以優先考慮使用NoSQL數據庫。

在考慮數據庫的成熟度;支持;分析和商業智能;管理及專業性等問題時,應優先考慮關系型數據庫。

3.MySQL和MongoDB之間最基本的區別是什么?

關系型數據庫與非關系型數據庫的區別,即數據存儲結構的不同。

4.MongoDB的特點是什么?

(1)面向文檔(2)高性能(3)高可用(4)易擴展(5)豐富的查詢語言

5.MongoDB支持存儲過程嗎?如果支持的話,怎么用?

MongoDB支持存儲過程,它是javascript寫的,保存在db.system.js表中。

6.如何理解MongoDB中的GridFS機制,MongoDB為何使用GridFS來存儲文件?

GridFS是一種將大型文件存儲在MongoDB中的文件規范。使用GridFS可以將大文件分隔成多個小文檔存放,這樣我們能夠有效的保存大文檔,而且解決了BSON對象有限制的問題。

7.為什么MongoDB的數據文件很大?

MongoDB采用的預分配空間的方式來防止文件碎片。

8.當更新一個正在被遷移的塊(Chunk)上的文檔時會發生什么?

更新操作會立即發生在舊的塊(Chunk)上,然后更改才會在所有權轉移前復制到新的分片上。

9.MongoDB在A:{B,C}上建立索引,查詢A:{B,C}和A:{C,B}都會使用索引嗎?

不會,只會在A:{B,C}上使用索引。

10.如果一個分片(Shard)停止或很慢的時候,發起一個查詢會怎樣?

如果一個分片停止了,除非查詢設置了“Partial”選項,否則查詢會返回一個錯誤。如果一個分片響應很慢,MongoDB會等待它的響應。


>>Redis、Memcache和MongoDB的區別

從以下幾個維度,對redis、memcache、mongoDB 做了對比,

1、性能

都比較高,性能對我們來說應該都不是瓶頸

總體來講,TPS方面redis和memcache差不多,要大于mongodb

2、操作的便利性

memcache數據結構單一

redis豐富一些,數據操作方面,redis更好一些,較少的網絡IO次數

mongodb支持豐富的數據表達,索引,最類似關系型數據庫,支持的查詢語言非常豐富

3、內存空間的大小和數據量的大小

redis在2.0版本后增加了自己的VM特性,突破物理內存的限制;可以對key value設置過期時間(類似memcache)

memcache可以修改最大可用內存,采用LRU算法

mongoDB適合大數據量的存儲,依賴操作系統VM做內存管理,吃內存也比較厲害,服務不要和別的服務在一起

4、可用性(單點問題)

對于單點問題,

redis,依賴客戶端來實現分布式讀寫;主從復制時,每次從節點重新連接主節點都要依賴整個快照,無增量復制,因性能和效率問題,

所以單點問題比較復雜;不支持自動sharding,需要依賴程序設定一致hash 機制。

一種替代方案是,不用redis本身的復制機制,采用自己做主動復制(多份存儲),或者改成增量復制的方式(需要自己實現),一致性問題和性能的權衡

Memcache本身沒有數據冗余機制,也沒必要;對于故障預防,采用依賴成熟的hash或者環狀的算法,解決單點故障引起的抖動問題。

mongoDB支持master-slave,replicaset(內部采用paxos選舉算法,自動故障恢復),auto sharding機制,對客戶端屏蔽了故障轉移和切分機制。

5、可靠性(持久化)

對于數據持久化和數據恢復,

redis支持(快照、AOF):依賴快照進行持久化,aof增強了可靠性的同時,對性能有所影響

memcache不支持,通常用在做緩存,提升性能;

MongoDB從1.8版本開始采用binlog方式支持持久化的可靠性

6、數據一致性(事務支持)

Memcache 在并發場景下,用cas保證一致性

redis事務支持比較弱,只能保證事務中的每個操作連續執行

mongoDB不支持事務

7、數據分析

mongoDB內置了數據分析的功能(mapreduce),其他不支持

8、應用場景

redis:數據量較小的更性能操作和運算上

memcache:用于在動態系統中減少數據庫負載,提升性能;做緩存,提高性能(適合讀多寫少,對于數據量比較大,可以采用sharding)

MongoDB:主要解決海量數據的訪問效率問題

redis有哪些持久化方案?

redis支持(快照、AOF):依賴快照進行持久化,aof增強了可靠性的同時,對性能有所影響

什么是緩存擊穿、什么緩存穿透

緩存雪崩

緩存雪崩是指在我們設置緩存時采用了相同的過期時間,導致緩存在某一時刻同時失效,請求全部轉發到DB,DB瞬時壓力過重雪崩。

解決方案

緩存失效時的雪崩效應對底層系統的沖擊非常可怕。大多數系統設計者考慮用加鎖或者隊列的方式保證緩存的單線 程(進程)寫,從而避免失效時大量的并發請求落到底層存儲系統上。這里分享一個簡單方案就時講緩存失效時間分散開,比如我們可以在原有的失效時間基礎上增加一個隨機值,比如1-5分鐘隨機,這樣每一個緩存的過期時間的重復率就會降低,就很難引發集體失效的事件。

緩存穿透

緩存穿透是指查詢一個一定不存在的數據,由于緩存是不命中時被動寫的,并且出于容錯考慮,如果從存儲層查不到數據則不寫入緩存,這將導致這個不存在的數據每次請求都要到存儲層去查詢,失去了緩存的意義。在流量大時,可能DB就掛掉了,要是有人利用不存在的key頻繁攻擊我們的應用,這就是漏洞。

解決方案

有很多種方法可以有效地解決緩存穿透問題,最常見的則是采用布隆過濾器,將所有可能存在的數據哈希到一個足夠大的bitmap中,一個一定不存在的數據會被 這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。另外也有一個更為簡單粗暴的方法(我們采用的就是這種),如果一個查詢返回的數據為空(不管是數 據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。

緩存擊穿

對于一些設置了過期時間的key,如果這些key可能會在某些時間點被超高并發地訪問,是一種非常“熱點”的數據。這個時候,需要考慮一個問題:緩存被“擊穿”的問題,這個和緩存雪崩的區別在于這里針對某一key緩存,前者則是很多key。

緩存在某個時間點過期的時候,恰好在這個時間點對這個Key有大量的并發請求過來,這些請求發現緩存過期一般都會從后端DB加載數據并回設到緩存,這個時候大并發的請求可能會瞬間把后端DB壓垮。

解決方案

使用互斥鎖(mutex key)

業界比較常用的做法,是使用mutex。簡單地來說,就是在緩存失效的時候(判斷拿出來的值為空),不是立即去load db,而是先使用緩存工具的某些帶成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一個mutex key,當操作返回成功時,再進行load db的操作并回設緩存;否則,就重試整個get緩存的方法。?

SETNX,是「SET if Not eXists」的縮寫,也就是只有不存在的時候才設置,可以利用它來實現鎖的效果。在redis2.6.1之前版本未實現setnx的過期時間,

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • -----------------------------------字符串類型-----------------...
    時光清淺03閱讀 180評論 0 0
  • pyspark.sql模塊 模塊上下文 Spark SQL和DataFrames的重要類: pyspark.sql...
    mpro閱讀 9,504評論 0 13
  • NOSQL類型簡介鍵值對:會使用到一個哈希表,表中有一個特定的鍵和一個指針指向特定的數據,如redis,volde...
    MicoCube閱讀 4,060評論 2 27
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,951評論 19 139
  • 雪 是廓天的使者 雪 是曠野的精靈 雪 是一樹一樹的梨花 雪 是一行一行的腳印 雪 是火爐邊的酒漪 雪 ...
    萬佛子閱讀 209評論 0 0