NoSQL
泛指非關係型數據庫
-
特點
- 易擴展
- 大數據量高性能
- 多樣靈活的數據類型
-
幹什麼
- KV
- Cache
- Persistence(持久化)
-
大數據時代的3V
- 海量
- 多樣
- 實時
-
互聯網需求的3高
- 高併發
- 高可擴
- 高性能
-
NoSQL數據模型——聚合模型
- KV鍵值(鍵值對)
- Bson(類似json)
- 列族
- 圖形
-
NoSQL數據庫的四大分類
- KV鍵值(Redis)
- 文檔型數據庫(MonggoDB)(bson格式比較多)
- 列存儲數據庫(HBase)
- 圖關係數據庫(Neo4J)
-
CAP+BASE
- 傳統的ACID
- A:原子性
- C:一致性
- I:獨立性
- D:持久性
- CAP(
最多隻能三選二
)- C:強一致性
- A:可用性
- P:分區容錯(分佈式容忍)性(分佈式系統必須)
- CA:傳統Oracle數據庫
- AP:大多數網站架構的選擇(弱移植性+AP)
- CP:Redis、MongoDB
- BASE
- BA:基本可用
- S:軟狀態
- E:最終一致*
- 傳統的ACID
Redis
(REmote DIctionary Server遠程字典服務器)
高性能的(Key/Value)分佈式內存數據庫
特點:
1. 持久化
2. 豐富的數據類型
3. 主從複製
能幹什麼
1. 內存存儲和持久化
2. 取最新N個數據的操作
3. 模擬類似httpsession需要設定過期時間的功能
4. 發佈、訂閱消息系統
5. 定時器、計數器
安裝
-
下載:https://redis.io
su root
然後輸入密碼進入root用戶
然後把安裝包放到linux下
tar xvf redis-5.0.8.tar
然後把解壓出來的文件放到/opt下(/opt是主機額外安裝軟件所擺放的目錄)
mv redis-5.0.8 /opt
-
進入redis目錄
make
安裝
(如果報錯沒gcc,輸入yum install gcc-c++
(需要網絡))
(如果安裝完後重新輸入make出現沒有此文件或3. 目錄,請輸入make distclean
再make
)make install
檢查安裝情況
-
安裝完成後在根目錄下新建一個myredis目錄,把redis.conf備份複製cp。
-
把
daemonize
的no
改爲yes
################################# GENERAL ##################################### #By default Redis does not run as a daemon. Use 'yes' if you need it. #Note that Redis will write a pid file in /var/run/redis.pid when daemonized. daemonize yes
啓動與退出
ps -ef|grep redis
//查看是否啓動redis
cd /usr/local/bin
//進入此目錄
redis-server /myredis/redis.conf
//啓動我們修改過的配置文件(原配置文件在最好不動)
redis-cli -p 6379
啓動(6379爲默認端口)
ping
//回覆PONG爲啓動成功
shutdown
exit
//shutdown後再exit退出
select [數字]
//切換數據庫(默認有16個數據庫)
dbsize
//查看當前數據庫key的數量
keys *
//查看所有key
clear
//清屏
flushdb
//清空當前數據庫鍵值對(慎用)
flushall
//清空所有數據庫鍵值對(慎用!!!)
- 單進程
- 默認16個數據庫,零號爲初始化
select [數字]
//進入第幾個數據庫(數字1爲零號數據庫,16爲第十五數據庫)dbsize
查看當前數據庫key的數量
5.統一密碼管理,16個數據庫相同密碼- redis索引都是從零開始
- 默認端口6379
Redis數據類型
1. Redis鍵(Key)
命令
set key value
//寫入鍵值對(只寫入當前數據庫)(如果key存在會被覆蓋)get key
:查看key的值keys *
:查詢所有key(支持*和?(*爲所有,?爲一位))exists key
:判斷key是否存在(1爲存在)move key db
:把key移到第幾個db(數據庫)ttl key
:查看還有幾秒過期,-1是永不過期,-2是已過期(過期即死亡,查不到)expire key 秒數
:設置key多久後過期(設置0秒瞬間去世)type key
:查看key是什麼類型del key
:刪除key
2. Redis字符串(String)
最基本的類型。 二進制安全的,即可以包含任何數據。
命令
-
set key value
-
get key
-
del key
-
append key value
:把value加到key值的後面 -
strlen key
:查看key值的長度 -
incr key
:值加1 (value是數字才能用) -
decr key
:值減1 (同上) -
incrby key 數字
:值加’數字’(同上) -
decrby key 數字
:值減’數字’(同上) -
getrange key 開始索引 結束索引
:獲取key值的指定片段(結束索引-1表示結尾) -
setrange key 插入索引 value
:把value從索引處開始覆蓋,value從開始到結束都會覆蓋原來的值(例:x1是abcde,setrange x1 0 xxx,x1是xxxde) -
setex key 秒數 value
:在set的基礎上增加設置存活時間 -
setnx key value
:在set的時候判斷有沒有值,有則不會覆蓋,沒有則寫入(防止覆蓋) -
mset k1 v1 k2 v2 ...
:set多個鍵值對 -
mget k1 k2 ...
:get多個key的值 -
msetnx
:同setnx,可以設置多個(如果其中有一個存在,則全部失效,插入失敗)
3. Redis列表(List)
簡單的字符串列表,按照插入順序排列,可以在頭部或尾部添加元素。底層是鏈表。
命令
l從頂部插入或取出,r從底部插入或取出
-
lpush listname 值1 值2 值3 ...
:寫入list(排序與輸入相反
,先寫的在底部,l:left) -
rpush listname x1 x2 x3 ...
:寫入list(排序與輸入相同
,先寫的在頂部,r:right) -
lrange lname 開始 結束索引
:獲取list指定的元素(結束索引-1爲結尾) -
lpop lname
:取出
頂部元素(序號最小的元素) -
rpop lname
:取出
底部元素(序號最大的元素) -
lindex lname 索引
:獲取索引對應的元素 -
llen lname
:獲取list的長度 -
lrem lname n個 元素
:刪除list中n個元素(例:list1->1,2,3,3,3,4,lrem list1 2 3,list1->1,2,3,4) -
ltrim lname 開始索引 結束索引
:截取指定片段後重新賦予lname -
rpoplpush list1 list2
:從list1底部拿一個元素到list2的頂部 -
lset lname 索引 value
:用value替代list中索引對應的元素 -
linsert lname before/after 值1 值2
:在list的值1之前/之後插入值2
4. *Redis集合(Set)
無序無重複的集合。
命令
-
sadd sname 值1 值2 值3 ...
:寫入set(重複只寫入一個)
smembers sname
:查看set裏的值
sismember sname value
:查看set裏是否存在value -
scard sname
:獲取set元素的個數 -
srem key value
:刪除set中元素 -
srandmember sname 數字n
:從set裏隨機獲取n個元素 -
spop key
:隨機取出
一個元素 -
smove set1 set2 值
:從set1中拿指定元素放到set2 -
sdiff set1 set2
:獲取set1中set2沒有的元素(差集) -
sinter set1 set2
:獲取set1和set2都有的元素(交集) -
sunion set1 set2
:獲取set1和set2所有不相同的元素(並集)
5. **Redis哈希(Hash)
一個鍵值對集合,類似java的map,特別適合存儲對象。KV中的V是鍵值對
命令
-
hset hname key value
:寫入哈希,如果存在,就寫入,不存在就新建再寫入 -
hget hname key
:獲取hash1中key對應的value -
hmset hname k1 v1 k2 v2 ...
:新建哈希並插入多對鍵值對 -
hmget hname k1 k2 ...
:獲取hash中多個key對應的value -
hgetall hname
:獲取hash中所有的鍵值對 -
hdel hname key
:刪除hash中指定的鍵值對 -
hlen hname
:查看hash中的鍵值對數 -
hexists hname key
:判斷hash中指定key是否存在 -
hkeys hname
:獲取hash中所有的key -
hvals hname
:獲取hash中所有的value -
hincrby hname key 數字n
:往hash中的key對應的value加n -
hincrbyfloat hname key 小數f
:往hash中的key對應的value加f -
hsetnx hname key value
:如果hash中存在要插入的key,則不插入
6. Redis有序集合Zset(sorted set)
zset和set一樣是string類型元素的集合,且不允許重複的成員。但是zset的每個元素都會關聯一個double類型的分數。zset成員是唯一的,但分數可以重複。redis就是按照每個成員的分數進行排序的。
在set基礎上,每個值加上一個score值,set是k1 v1 v2 v3,zset是k1 score1 v1 score2 v2
命令
-
zadd zsname s1 v1 s2 v2 ...
:插入zset -
zrange zsname 開始索引 結束索引
:查看zset中指定區域索引的value -
zrangebyscore zsname 開始score 結束score
:按score查詢zset中的value
例1:zrangebyscore zset1 (60 (90 大於60小於90
例2:zrangebyscore zset1 60 90 limit 2 3 分頁顯示,從索引爲2開始,獲取包括自己及往下2個 -
zrem zsname value
:刪除zset中指定的value -
zcard zsname
:查詢zset中value的個數 -
zcount zsname 開始score 結束score
:查詢在練歌score之間元素的個數 -
zrank zsname value
:查看value的索引 -
zscore zsname value
:查看value對應的score -
zrevrank zsname value
:逆序獲取value的索引(反着數) -
zrevrange zsname 開始索引 結束索引
:與zrange作用相似,不過得到的結果是反着排序輸出 -
zrevrangebyscore 結束score 開始score
:與zrangebyscore作用相似,不過也是反着的
配置文件redis.conf
Units單位
- 配置文件就開始定義了基本的度量單位,只支持bytes,不支持bit。
- 大小寫不敏感。
INCLUDES包含
- redis.conf文件中可以包含其他配置文件。
NETWORK網絡
bind 127.0.0.1
綁定的端口/網絡protected-mode yes
port 6379
端口號。tcp-backlog 511
設置tcp的backlog,backlog是一個連接隊列,backlog隊列總和=未完成的三次握手隊列+已完成的三次握手隊列。高併發環境下用高backlog值避免慢客戶端連接問題。timeout 0
客戶端閒置N秒後關閉連接(0爲不關閉)。tcp-keepalive 300
TCP保持活動狀態。
作用:
1)檢測死亡的同伴。
2)從網絡角度使連接活躍起來
此選項的合理值爲300秒
GENERAL通用
通用常用的標準化配置
daemonize no
默認情況下,Redis不會作爲守護程序運行。需要將no改爲yes。Redis守護進程將在/var/run/redis.pid中寫入一個pid文件。(使用docker不需要改yes)supervised no
pidfile /var/run/redis_6379.pid
進程管道id文件Loglevel notice
日誌級別- debug:開發測試階段使用(日誌信息最多)
- verbose
- notice
- warning(日誌信息最少)
logfile ""
日誌文件的名字,不寫也可以是空字符串。databases 16
默認16個數據庫,默認數據庫爲0數據庫,select切換數據庫。- always-show-logo yes
SNAPSHOTTING快照
save <seconds> <changes>
seconds:多少時間內
changes:修改幾次
指定在多長時間,有多少次更新操作,就將數據同步到數據文件,可以多個save條件配合。
默認三種:-
save 900 1 #15分鐘改1次
-
save 300 10 #5分鐘改10次
-
save 60 10000 #1分鐘改10000次
-
如果想禁用RDB持久化的策略,只要不設置save或設置save ""就可以了。
也可以在命令界面下輸入save或bgsave立刻備份。
* save save時只管保存,其他不管,全部阻塞
* bgsave redis後臺異步進行快照操作,快照的同事還可以響應客戶端請求。
執行flushall也會產生dump.rdb文件,但裏面是空的,無意義。
2. stop-writes-on-bgsave-error yes
後臺保存時出錯,前臺停止寫入,默認yes。
3. rdbcompression yes
指定存儲到本地時是否LZF壓縮數據,默認yes。
4. rdbchecksum
在存儲快照後,讓reids使用CRC64算法進行數據校驗,會增加大約10%的性能消耗,默認yes。
5. dbfilename dump.rdb
指定本地數據庫文件名。
6. dir ./
指定本地數據庫存放目錄。
REPLICATION複製
masterauth <master-password>
SECURITY安全
requirepass foobared
設置redis連接密碼,默認關閉
也可以在redis服務器命令框下設置
config get requirepass
:查看密碼
config set requirepass password
:設置密碼
auth password
:輸入密碼
CLIENTS限制
-
maxclients 10000
最多連接數,0則不限制 -
maxmemory <bytes>
最大的內存(512M) -
maxmemory-policy noeviction
緩存的移除策略(過期策略)
lru:最近最少使用
lfu:最不頻繁使用
random:隨機
ttl:有限時間內
noeviction:永不過期(工作不推薦)- volatile-lru:使用設置了過期時間的鍵中的近似LRU退出。
- allkeys-lru:使用近似的LRU退出任何密鑰。
- volatile-lfu:使用已設置有效期的鍵中的近似LFU退出。
- allkeys-lfu:使用近似的LFU退出任何密鑰。
- volatile-random:從設置了過期的密鑰中刪除一個隨機密鑰。
- allkeys-random:刪除隨機密鑰,任何密鑰。
- volatile-ttl:刪除最接近到期時間(較小的TTL)的密鑰。
- noeviction:不要驅逐任何東西,只在寫操作時返回一個錯誤。
-
maxmemory-samples 5
設置樣本數量,默認5個
APPEND ONLY MODE追加
-
appendonly no
aof的持久化,將redis執行過的所有寫指令記錄下來,默認no,需要開啓。 -
appendfilename "appendonly.aof"
aop文件名字,默認appendonly.aof"。 -
appendfsync everysec
- no:
- always:同步持久化,每次發生數據變更會被立即記錄到磁盤,性能較差但數據完整性比較好。
- everysec:出廠默認推薦,異步操作,每秒記錄,如果一秒內宕機,有數據丟失。
-
no-appendfsync-on-rewrite no
重寫時是否可以運用yunyongAppendfsync,用默認no即可,保證數據安全性。 -
auto-aof-rewrite-percentage 100
設置重寫的基準值:文件大小翻一倍(100爲100%)觸發。 -
auto-aof-rewrite-min-size 64mb
設置重寫的基準值:文件大於64mb觸發。(工作時可以設置到5GB以上)
redis的持久化
RDB(Redis DataBase)
在指定的時間間隔內將內存中的數據集快照寫入磁盤,行話裏的Snapshot快照,它恢復時是將快照文件直接讀到內存裏
恢復
如果電腦出現了問題,我們需要恢復原來的數據。
- 正常恢復
重啓就會重新加載。 - 異常恢復
如果dump.rdb出現異常(如在寫入dump.rdb時斷電等),需要先將dump.rdb進行修復(redis-check-rdb --fix dump.rdb
),然後重啓恢復數據。
優勢:
劣勢:
總結:
AOF(Append Only File)
如果appendonly.aof和dump.rdb同時存在,加載的是appendonly.aof。
恢復
在配置文件中,將appendonly
設置成yes,我們在寫入數據時,就會記錄到appendonly.aof,如果電腦出現了問題,我們需要恢復原來的數據。
-
正常恢復
重啓就會重新加載。 -
異常恢復
如果appendonly.aof出現異常(如在寫入appendonly.aof時斷電等),需要先將appendonly.aof進行修復(
redis-check-aof --fix appendonly.aof
),然後重啓恢復數據。
Rewrite
優勢
劣勢
總結:
RDB與AOF
redis的事務
常用命令
discard
:放棄執行事務塊內的所有命令(取消事務)。exec
:執行所有事務塊內的命令(執行事務)。multi
:標記一個事務塊的開始,接下來的命令都會加入事務隊列中(開始事務)。unwatch
:取消watch命令對所有key的監控(取消監控)。watch key1 key2 ...
:監視一個或多個key,如果在事務執行前這些key有被改動,那麼事務將被打斷(監控)。
正常執行exec
放棄事務discard
1. 全體連坐
multi之後,只要其中一個命令直接返回error,則在exec時也會返回error,執行失敗。(如java的編譯時異常)
2. 冤頭債主(不保證原子性)
multi之後,其中一個命令邏輯錯誤但沒直接返回error,則exec成功,error的返回error,ok的返回ok(如java的運行時異常)。
3. *watch監控
悲觀鎖(上鎖)
樂觀鎖(不上鎖)
CAS(check and set)
檢查並設置
事務的三階段
事務的三特性
redis的訂閱/發佈
不推薦充當消息中間件(瞭解redis有這功能即可)
命令
redis的消息
讀寫分離
容災恢復
info replication
:查看信息
slaveof 127.0.0.1 端口號
:把本數據庫設置成指定端口號的從庫(沒設置前都是master,設置了之後爲slave)
當設置完從庫後,從庫就複製了主庫所有的數據,包括slaveof之前設置的數據都會被複制到從庫。(只有master主庫才能寫,slave從庫只負責讀)
一主二從(配從不配主)
這裏設置了三個redis,6379當主庫,6380和6381爲6379從庫。
-
當主庫掛了(把主庫exit來模擬死機)之後,從庫還是slave,但是連接狀態變爲down,從庫待命等待主庫,當主庫回來後,從庫依然可以獲取主庫寫入的數據。
-
當其中一個從庫掛了,重啓後,不再是slave,而是master,需要重新設置。
薪火相傳
這裏設置了三個redis,6379當主庫,6380是6379的從庫,6381是從庫6380。
在主庫6379寫的數據,6380和6380的從庫6381都能拿到。
-
當主庫6379掛了,6380的連接狀態爲down,6381的連接狀態依舊是up,主庫重新連接後6380和6381都能獲得6379的值。
-
當從庫6380掛了,6379沒從庫,而6381連接狀態爲down,6381此時獲取不到6379更新的數據,6380重新連接後,需要重新連接6379,6381才能拿到最新的數據。
反客爲主
當主庫掛了,需要一個從庫來當主庫。
slaveof no one
:讓一個從庫來當主庫,另一個從庫重新連接這個新主庫。
複製的原理
首次連接是全量複製(全部複製),其他是增量複製(只複製新的)。
*哨兵模式(反客爲主的自動版)
- 一主二從,79下掛着80和81
- 在/myredis目錄下新建
sentinel.conf
文件,名字不能錯。
在sentinel.conf文件中寫入sentinel monitor 被監控數據庫名字(自己起名字host6379) 127.0.0.1 6379 1
- 啓動哨兵
redis-sentinel /myredis/sentinel.conf
當主庫6379掛了,哨兵就會進行投票,選出一個從庫來擔任主庫(票數相同則重新投票)。
當6379重新啓動後,哨兵會將6379變成slave掛在新主庫下面。
這時,6380掛了,哨兵會在6379和6381之間選主庫。
當只有兩個庫時,且新主庫又掛了,剩下最後一個從庫擔任主庫。
如果都掛了,哨兵會等數據庫重新啓動,當有一個數據庫啓動後,哨兵會在一個啓動兩個死機的數據庫中選出新主庫,新主庫不一定是重新啓動了的數據庫,有可能是死機的數據庫。
複製的缺點
由於所有的寫操作都是先在Master上操作,然後同步更新到Slave上,所以從Master同步到slave機器有一定的延遲,當系統很繁忙的時候,延遲問題會更加嚴重, Slave機器數量的增加也會使這個問題更加嚴重。
Jedis
Jedis的API與redis命令基本一致,可以直接參照redis的命令。
1. 測試連接
終端啓動redis。
然後在linux下的IDEA,新建maven工程,選擇webapp骨架。
導入jedis包座標:
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
新建個java文件。
Jedis jedis = new Jedis("127.0.0.1", 6379);
System.out.println(jedis.ping());//返回PONG證明連接成功。
2. set和get
- set添加鍵值對
jedis.set("k1", "v1");
jedis.set("k2", "v3");
jedis.set("k3", "v3");
在終端keys *
查看添加的數據。
- get獲得value
System.out.println("k1");
- keys獲取所有數據
Set<String> keys = jedis.keys("*");
3. 數據類型
1. key
2. String
3. List
4. Set
5. Hash
6. zSet
4. 事務
Transaction transaction = jedis.multi(); //開啓事務
transaction.set("k4", "v4"); //添加到事務隊列
transaction.exec(); //執行事務
//transaction.discard(); //取消事務
jedis.watch("k1"); //加監控
jedis.unwatch("k1"); //取消監控
5. 主從複製(配從不配主)
開啓6379和6380,兩個都爲master
Jedis jedis_M = new Jedis("127.0.0.1", 6379);
Jedis jedis_S = new Jedis("127.0.0.1", 6380);
jedis_S.slaveof("127.0.0.1", 6379);
jedis_M.set("k1", "v1"); //主寫
System.out.println(jedis_S.get("k1")); //從讀
6. RedisPool連接池
學習redis是在b站看尚硅谷陽哥的視頻的。
https://www.bilibili.com/video/BV1oW411u75R?p=1
上面有些圖片就是視頻中的內容,本人菜鳥一枚,筆記寫的不全不好的地方,請多多見諒。