為什么要用Redis
NoSQL:
NoSQL是不同于傳統(tǒng)的關(guān)系數(shù)據(jù)庫的數(shù)據(jù)庫管理系統(tǒng)的統(tǒng)稱。其兩者最重要的區(qū)別是NoSQL不使用SQL作為查詢語言。 NoSQL數(shù)據(jù)存儲(chǔ)可以不需要固定的表格模式。NoSQL是基于鍵值對(duì)的,可以想象成表中的主鍵和值的對(duì)應(yīng)關(guān)系。
常見的NoSQL有:redis、memcached、mongodb、guava(loadingCache)
redis的定義:
Redis 是一個(gè)開源(BSD許可)的,內(nèi)存中的數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)系統(tǒng),它可以用作數(shù)據(jù)庫、緩存和消息中間件。 它支持多 種類型的數(shù)據(jù)結(jié)構(gòu),如 字符串(strings)、散列(hashes)、 列表(lists)、 集合(sets)、 有序集合(sorted sets)等。
作為同款功能的內(nèi)存緩存產(chǎn)品,redis和memcached各有什么優(yōu)勢(shì):
內(nèi)存管理機(jī)制
Memcached默認(rèn)使用Slab Allocation機(jī)制管理內(nèi)存,其主要思想是按照預(yù)先規(guī)定的大小, 將分配的內(nèi)存分割成特定長度的塊以存儲(chǔ)相應(yīng)長度的key-value數(shù)據(jù)記錄,以完全解決內(nèi)存碎 片問題??臻e列表進(jìn)行判斷存儲(chǔ)狀態(tài),【類似于Java虛擬機(jī)對(duì)象的分配,空閑列表】
Redis使用現(xiàn)場(chǎng)申請(qǐng)內(nèi)存的方式來存儲(chǔ)數(shù)據(jù),并且很少使用free-list等方式來優(yōu)化內(nèi)存分配,會(huì)在一定程度上存在內(nèi)存碎片,【CPU內(nèi)存是連續(xù),類似于Java虛擬機(jī)對(duì)象的分配,直接內(nèi)存分配(指針碰撞)】
數(shù)據(jù)持久化方案
memcached不支持內(nèi)存數(shù)據(jù)的持久化操作,所有的數(shù)據(jù)都以in-memory的形式存儲(chǔ)。
redis支持持久化操作。redis提供了兩種不同的持久化方法來講數(shù)據(jù)存儲(chǔ)到硬盤里面, 第一種是rdb形式,一種是aof形式:
rdb:屬于全量數(shù)據(jù)備份,備份的是數(shù)據(jù)
aof:append only if,增量持久化備份,備份的是指令
緩存數(shù)據(jù)過期機(jī)制
概念:key,設(shè)計(jì)一個(gè)小時(shí)之后過期,超過一個(gè)小時(shí)查數(shù)據(jù)就會(huì)查不到
Memcached 在刪除失效主鍵時(shí)也是采用的消極方法,即 Memcached 內(nèi)部也不會(huì)監(jiān)視主鍵是否失效,而是在通過 Get 訪問主鍵時(shí)才會(huì)檢查其是否已經(jīng)失效
Redis 定時(shí)、定期等多種緩存失效機(jī)制,減少內(nèi)存泄漏
支持的數(shù)據(jù)類型
Memcached支持單一數(shù)據(jù)類型:[k,v]
redis支持五種數(shù)據(jù)類型:【字符串(strings)、散列(hashes)、 列表(lists)、 集合(sets)、 有序集合(sorted sets)】
redis作為數(shù)據(jù)庫的使用有什么優(yōu)缺點(diǎn)?
優(yōu)點(diǎn):沒有Scheme約束,數(shù)據(jù)結(jié)構(gòu)的變更相對(duì)容易,一開始確定數(shù)據(jù)類型, 抗壓能力強(qiáng),性能極高,10萬/qps
缺點(diǎn):沒有索引,沒有外鍵,缺少int/date等基本數(shù)據(jù)類型,多條件查詢需要通過集合內(nèi)聯(lián)(sinter,zinterstore) 和連接間接實(shí)現(xiàn)開發(fā)效率低,可維護(hù)性不佳
redis作為緩存的使用,搭配數(shù)據(jù)庫使用的兩種方案
1.jedis整合使用方案 set key,value ["11","22"] 第一層在緩存進(jìn)行查詢,如果得到數(shù)據(jù)則直接返回, 第二層在數(shù)據(jù)庫進(jìn)行查詢,并且刷新緩存,方便下次查詢 ["33,"44"]
2.作為mybatis/hibernate二級(jí)緩存使用方案,一級(jí)緩存:sqlSession,進(jìn)程緩存,單次鏈接有效
Redis安裝啟動(dòng)
redis4.0安裝步驟:
- 安裝wget yum install wget
- 下載redis安裝包 wget http://download.redis.io/releases/redis-4.0.6.tar.gz
- 解壓壓縮包 tar -zxvf redis-4.0.6.tar.gz
- yum install gcc
- 跳轉(zhuǎn)到redis解壓目錄下 cd redis-4.0.6
- 編譯安裝 make MALLOC=libc
- cd src ./redis-server
redis三種啟動(dòng)方式以及其中的使用區(qū)別
1.直接啟動(dòng)(例如:cd src ./redis-server)
2.通過指定配置文件啟動(dòng)(例如:cd src ./redis-server ../redis.conf)
3.使用redis啟動(dòng)腳本設(shè)置開機(jī)啟動(dòng),linux配置開機(jī)自啟動(dòng)/etc/init.d
配置步驟:
- 啟動(dòng)腳本 redis_init_script 位于Redis的 /utils/ 目錄下
- mkdir /etc/redis
- cp redis.conf /etc/redis/6379.conf
- 將啟動(dòng)腳本復(fù)制到/etc/init.d目錄下,本例將啟動(dòng)腳本命名為redisd(通常都以d結(jié)尾表示是后臺(tái)自啟動(dòng)服務(wù))。
cp redis_init_script /etc/init.d/redisd - 設(shè)置為開機(jī)自啟動(dòng),直接配置開啟自啟動(dòng) chkconfig redisd on 發(fā)現(xiàn)錯(cuò)誤: service redisd does not support chkconfig
解決辦法:在啟動(dòng)腳本開頭添加如下注釋來修改運(yùn)行級(jí)別
#!/bin/sh # chkconfig: 2345 90 10 - 設(shè)置為開機(jī)自啟動(dòng)服務(wù)器
chkconfig redisd on
service redisd start 打開服務(wù)
service redisd stop 關(guān)閉服務(wù)
Redis五種數(shù)據(jù)類型和消息訂閱
Key / Value數(shù)據(jù)類型
String是最常用的一種數(shù)據(jù)類型,普通的key/value存儲(chǔ)都可以歸為此類。
常用的命令:
set/get
設(shè)置key對(duì)應(yīng)的值為String類型的value
獲取key對(duì)應(yīng)的值mget
批量獲取多個(gè)key的值,如果可以不存在則返回nilincr && incrby
incr對(duì)key對(duì)應(yīng)的值進(jìn)行加加操作,并返回新的值;incrby加指定值decr && decrby
decr 對(duì)key對(duì)應(yīng)的值進(jìn)行減減操作,并返回新的值;decrby減指定值setnx
設(shè)置key對(duì)應(yīng)的值為String類型的value,如果key已經(jīng)存在則返回0setex
設(shè)置key對(duì)應(yīng)的值為String類型的value,并設(shè)定有效期其他命令
getrange:獲取key對(duì)應(yīng)value的子字符串
mset:批量設(shè)置多個(gè)key的值,如果成功表示所有值都被設(shè)置,否則返回0表示沒有任何值被設(shè)置
msetnx:同mset,不存在就設(shè)置,不會(huì)覆蓋已有的key
getset:設(shè)置key的值,并返回key舊的值
append:給指定key的value追加字符串,并返回新字符串的長度
Hash類型
- Hash是一個(gè)String類型的field和value之間的映射表
- redis的Hash數(shù)據(jù)類型的key(hash表名稱)對(duì)應(yīng)的value實(shí)際的內(nèi)部存儲(chǔ)結(jié)構(gòu)為一個(gè)HashMap
- Hash特別適合存儲(chǔ)對(duì)象
- 相對(duì)于把一個(gè)對(duì)象的每個(gè)屬性存儲(chǔ)為String類型,將整個(gè)對(duì)象存儲(chǔ)在Hash類型中會(huì)占用更少內(nèi)存。
- 所存儲(chǔ)的成員較少時(shí)數(shù)據(jù)存儲(chǔ)為zipmap,當(dāng)成員數(shù)量增大時(shí)會(huì)自動(dòng)轉(zhuǎn)成真正的HashMap,此時(shí)encoding為ht。
- 運(yùn)用場(chǎng)景:如用一個(gè)對(duì)象來存儲(chǔ)用戶信息,商品信息,訂單信息等等。
- Hash命令講解
hset——設(shè)置key對(duì)應(yīng)的HashMap中的field的value
hget——獲取key對(duì)應(yīng)的HashMap中的field的value
hgetall——獲取key對(duì)應(yīng)的HashMap中的所有field的value
hlen——返回key對(duì)應(yīng)的HashMap中的field的數(shù)量
List類型
- lpush——在key對(duì)應(yīng)的list的頭部添加一個(gè)元素
- lrange——獲取key對(duì)應(yīng)的list的指定下標(biāo)范圍的元素,-1表示獲取所有元素
- lpop——從key對(duì)應(yīng)的list的尾部刪除一個(gè)元素,并返回該元素
- rpush——在key對(duì)應(yīng)的list的尾部添加一個(gè)元素
- rpop——從key對(duì)應(yīng)的list的尾部刪除一個(gè)元素,并返回該元素
Set類型
- sadd——在key對(duì)應(yīng)的set中添加一個(gè)元素
- smembers——獲取key對(duì)應(yīng)的set的所有元素
- spop——隨機(jī)返回并刪除key對(duì)應(yīng)的set中的一個(gè)元素
- suion——求給定key對(duì)應(yīng)的set并集
- sinter——求給定key對(duì)應(yīng)的set交集
SortSet類型
set的基礎(chǔ)增加順序score,再根據(jù)score進(jìn)行排序
實(shí)戰(zhàn)(用途):通過sortset實(shí)現(xiàn)排行榜
- zadd ——在key對(duì)應(yīng)的zset中添加一個(gè)元素
- zrange——獲取key對(duì)應(yīng)的zset中指定范圍的元素,-1表示獲取所有元素
- zrem——?jiǎng)h除key對(duì)應(yīng)的zset中的一個(gè)元素
- zrangebyscore——返回有序集key中,指定分?jǐn)?shù)范圍的元素列表,排行榜中運(yùn)用
- zrank——返回key對(duì)應(yīng)的zset中指定member的排名。其中member按score值遞增(從小到大); 排名以0為底,也就是說,score值最小的成員排名為0,排行榜中運(yùn)用
- set是通過hashmap存儲(chǔ),key對(duì)應(yīng)set的元素,value是空對(duì)象 sortset是怎么存儲(chǔ)并實(shí)現(xiàn)排序的呢,hashmap存儲(chǔ),還加了一層跳躍表 跳躍表:相當(dāng)于雙向鏈表,在其基礎(chǔ)上添加前往比當(dāng)前元素大的跳轉(zhuǎn)鏈接
redis消息訂閱發(fā)布
作用:發(fā)布訂閱類似于信息管道,用來進(jìn)行系統(tǒng)之間消息解耦,類似于mq,rabbitmq、rocketmq、kafka、activemq主要有消息發(fā)布者和消息訂閱者。比如運(yùn)用于:訂單支付成功,會(huì)員系統(tǒng)加積分、錢包進(jìn)行扣錢操作、發(fā)貨系統(tǒng)(下發(fā)商品)
PUBLISH 將信息message發(fā)送到指定的頻道channel。返回收到消息的客戶端數(shù)量
SUBSCRIBE 訂閱給指定頻道的信息
UNSUBSCRIBE 取消訂閱指定的頻道,如果不指定,則取消訂閱所有的頻道。
redis的消息訂閱發(fā)布和mq對(duì)比?
redis發(fā)布訂閱功能比較薄弱但比較輕量級(jí),mq消息持久化,數(shù)據(jù)可靠性比較差,無后臺(tái)功能可msgId、msgKey進(jìn)行查詢消息
傳統(tǒng)關(guān)系型數(shù)據(jù)庫事務(wù)與Redis事務(wù)
事務(wù)概要和事務(wù)隔離級(jí)別
一個(gè)數(shù)據(jù)庫事務(wù)通常包含了一個(gè)序列的對(duì)數(shù)據(jù)庫的讀/寫操作。它的存在包含有以下兩個(gè)目的:
1)為數(shù)據(jù)庫操作序列提供了一個(gè)從失敗中恢復(fù)到正常狀態(tài)的方法,同時(shí)提供了數(shù)據(jù)庫即使在異常狀態(tài)下仍能保持一致性的方法。
2)當(dāng)多個(gè)應(yīng)用程序在并發(fā)訪問數(shù)據(jù)庫時(shí),可以在這些應(yīng)用程序之間提供一個(gè)隔離方法,以防止彼此的操作互相干擾。事務(wù)的ACID四大特性
原子性(Atomicity):事務(wù)作為一個(gè)整體被執(zhí)行,包含在其中的對(duì)數(shù)據(jù)庫的操作要么全部被執(zhí)行,要么都不執(zhí)行
一致性(Consistency):事務(wù)應(yīng)確保數(shù)據(jù)庫的狀態(tài)從一個(gè)一致狀態(tài)轉(zhuǎn)變?yōu)榱硪粋€(gè)一致狀態(tài)。一致狀態(tài)的含義是數(shù)據(jù)庫中的數(shù)據(jù)應(yīng)滿足完整性約束
隔離性(Isolation):多個(gè)事務(wù)并發(fā)執(zhí)行時(shí),一個(gè)事務(wù)的執(zhí)行不應(yīng)影響其他事務(wù)的執(zhí)行
持久性(Durability):已被提交的事務(wù)對(duì)數(shù)據(jù)庫的修改應(yīng)該永久保存在數(shù)據(jù)庫中事務(wù)隔離機(jī)制
語法:set global transaction isolation level read uncommitted;
種類:read uncommitted、read committed、repeatable read、serializable
mysql事務(wù)隔離機(jī)制和MVCC
redis事務(wù)隔離機(jī)制可重復(fù)讀講解(repeatable read)
select @@tx_isolation ; 查看事務(wù)類型
-
InnoDB MVCC多版本并發(fā)控制
在每一行數(shù)據(jù)中額外保存兩個(gè)隱藏的列:當(dāng)前行創(chuàng)建時(shí)的版本號(hào)和刪除時(shí)的版本號(hào)(可能為空,其實(shí)還有一列稱為回滾指針,用于事務(wù)回滾)。這里的版本號(hào)并不是實(shí)際的時(shí)間值,而是系統(tǒng)版本號(hào)。每開始新的事務(wù),系統(tǒng)版本號(hào)都會(huì)自動(dòng)遞增。事務(wù)開始時(shí)刻的系統(tǒng)版本號(hào)會(huì)作為事務(wù)的版本號(hào), 用來和查詢每行記錄的版本號(hào)進(jìn)行比較
MVCC.png
redis事務(wù)機(jī)制
MULTI 與 EXEC命令
以 MULTI 開始一個(gè)事務(wù),然后將多個(gè)命令入隊(duì)到事務(wù)中, 最后由 EXEC 命令觸發(fā)事務(wù), 一并執(zhí)行事務(wù)中的所有命令DISCARD命令
DISCARD 命令用于取消一個(gè)事務(wù), 它清空客戶端的整個(gè)事務(wù)隊(duì)列, 然后將客戶端從事務(wù)狀態(tài)調(diào)整回非事務(wù)狀態(tài), 最后返回字符串 OK 給客戶端, 說明事務(wù)已被取消-
WATCH命令
WATCH 命令用于在事務(wù)開始之前監(jiān)視任意數(shù)量的鍵: 當(dāng)調(diào)用 EXEC 命令執(zhí)行事務(wù)時(shí), 如果任意一個(gè)被監(jiān)視的鍵已經(jīng)被其他客戶端修改了, 那么整個(gè)事務(wù)不再執(zhí)行, 直接返回失敗。
事務(wù)狀態(tài).png
處理事物.png
redis事務(wù)ACID
原子性(Atomicity)
單個(gè) Redis 命令的執(zhí)行是原子性的,但 Redis 沒有在事務(wù)上增加任何維持原子性的機(jī)制,所以 Redis 事務(wù)的執(zhí)行并不是原子性的。如果一個(gè)事務(wù)隊(duì)列中的所有命令都被成功地執(zhí)行,那么稱這個(gè)事務(wù)執(zhí)行成功一致性(Consistency)
入隊(duì)錯(cuò)誤
在命令入隊(duì)的過程中,如果客戶端向服務(wù)器發(fā)送了錯(cuò)誤的命令,比如命令的參數(shù)數(shù)量不對(duì)等等, 那么服務(wù)器將向客戶端返回一個(gè)出錯(cuò)信息, 并且將客戶端的事務(wù)狀態(tài)設(shè)為 REDIS_DIRTY_EXEC 。
執(zhí)行錯(cuò)誤
如果命令在事務(wù)執(zhí)行的過程中發(fā)生錯(cuò)誤,比如說,對(duì)一個(gè)不同類型的 key 執(zhí)行了錯(cuò)誤的操作, 那么 Redis 只會(huì)將錯(cuò)誤包含在事務(wù)的結(jié)果中, 這不會(huì)引起事務(wù)中斷或整個(gè)失敗,不會(huì)影響已執(zhí)行事務(wù)命令的結(jié)果,也不會(huì)影響后面要執(zhí)行的事務(wù)命令, 所以它對(duì)事務(wù)的一致性也沒有影響
隔離性(Isolation)
WATCH 命令用于在事務(wù)開始之前監(jiān)視任意數(shù)量的鍵: 當(dāng)調(diào)用 EXEC 命令執(zhí)行事務(wù)時(shí), 如果任意一個(gè)被監(jiān)視的鍵已經(jīng)被其他客戶端修改了, 那么整個(gè)事務(wù)不再執(zhí)行, 直接返回失敗持久性(Durability)
因?yàn)槭聞?wù)不過是用隊(duì)列包裹起了一組 Redis 命令,并沒有提供任何額外的持久性功能,所以事務(wù)的持久性由 Redis 所使用的持久化模式?jīng)Q定


