NoSQL的概述
什么是NoSQL
- Not Only Sql
- 非關(guān)系型數(shù)據(jù)庫
為什么需要NoSQL
- High performance -- 高并發(fā)讀寫
- Huge Storage -- 海量數(shù)據(jù)的高效率存儲與訪問
- High Scalability && High Availablity -- 高可擴展和高可用
NoSQL產(chǎn)品
- Redis
- MongoDB
- membase
NoSQL數(shù)據(jù)庫的四大分類
- 鍵值(K-V)存儲:快速查詢篷牌,數(shù)據(jù)沒有結(jié)構(gòu)化
- 列存儲(Hbase):查找速度快娃磺,擴展強叫倍,功能局限
- 文檔數(shù)據(jù)庫(MongoDB):數(shù)據(jù)結(jié)構(gòu)要求不嚴格,查詢性能不是很高听诸,缺少統(tǒng)一查詢的語法
- 圖形數(shù)據(jù)庫(Neo4j晌梨,infinite):利用圖結(jié)構(gòu)的算法须妻,需要的整個圖做計算才能拿到結(jié)果荒吏,不利于分布式的部署
NoSQL特點
- 易擴展,非關(guān)系型
- 靈活的數(shù)據(jù)模型
- 大量數(shù)據(jù)瞧挤,高性能
- 高可用
Redis
高性能鍵值對數(shù)據(jù)庫特恬,使用C語言開發(fā),支持的數(shù)據(jù)類型如下:
- 字符串類型
- 列表類型
- 有序集合類型
- 散列類型
- 集合類型
讀寫性能:50個并發(fā)程序執(zhí)行10萬個請求役首,讀速度:100000次/秒 寫速度:81000次/秒
Redis應(yīng)用場景
- 緩存
- 任務(wù)隊列
- 網(wǎng)站訪問統(tǒng)計
- 數(shù)據(jù)過期處理
- 應(yīng)用排行榜
- 分布式集群架構(gòu)中的session分離
redis安裝
自行g(shù)oogle或者百度
Jedis入門
什么是jedis 宋税?
Jedis官方github讼油,readme介紹如下:
Jedis is a blazingly small and sane Redis java client.
Jedis was conceived to be EASY to use.
Jedis is fully compatible with redis 2.8.x and 3.x.x.
Jedis是一個超級炫酷輕量和智能與一體的Redis的Java客戶端矮台,大家都覺得Jedis非常的好用根时,并且完全的兼容Redis2.8.x and 3.x.x.與此同時蛤迎,Jedis也是Redis官方推薦使用的Redis的Java客戶端。
Jedis的基本使用
@Test
/**
* jedis 單例測試
*/
public void demo1() {
// 1.設(shè)置ip地址和端口
Jedis jedis = new Jedis("127.0.0.1", 6379);
// 2.保存數(shù)據(jù)
jedis.set("name", "hello");
// 3.獲取數(shù)據(jù)
String v = jedis.get("name");
System.out.println(v);
// 4.釋放資源
jedis.close();
}
@Test
/**
* 使用jedis連接池
*/
public void demo2() {
//創(chuàng)建jedis連接池配置對象:
JedisPoolConfig config = new JedisPoolConfig();
//配置jedisPoolConfig
config.setMaxTotal(30);
config.setMaxIdle(10);
//創(chuàng)建jedis連接池
JedisPool jedisPool = new JedisPool(config, "127.0.0.1", 6379);
//使用連接池獲取核心對象:
Jedis jedis = null;
try {
//獲取對象
jedis = jedisPool.getResource();
//設(shè)置數(shù)據(jù)
jedis.set("name", "hashMap");
//獲取數(shù)據(jù)
String value = jedis.get("name");
System.out.println(value);
} catch (Exception e) {
System.out.println(e.getMessage());
} finally {
//釋放資源
if (jedis != null) {
jedis.close();
}
if (jedisPool != null) {
jedisPool.close();
}
}
}
Redis數(shù)據(jù)結(jié)構(gòu)
- 字符串(String)常用
- 哈希(hash)常用
- 字符串列表(list)
- 字符串集合(set)
- 有序字符串集合(sorted list)
key的定義注意點:
- 不要太長,占用內(nèi)容大宜咒,且查找效率降低
- 不要太短把鉴,否則降低可讀性
存儲String
以二進制的形式進行存儲操作的庭砍,意味著String的存儲和獲取的結(jié)果是相同的
最多容納的value:512M
存儲String的常用命令:
- 賦值
- set key value
- getset key newvalue
--> 先獲取key的值然后將key對應(yīng)的value設(shè)置為newvalue
- 取值
- get key
--> 獲取這個key對應(yīng)的value
- 刪除
- del key
--> 返回一個(interger)1表示刪除成功怠缸,之后get key
--> 會得到(nil)表示這個key沒有value
- 數(shù)值增減
incr num
--> 如果num不存在初始化為0然后加1,num變?yōu)?
--> 如果num存在并且可以轉(zhuǎn)為整形概耻,num直接加1
--> 如果num存在但是不能轉(zhuǎn)為整形鞠柄,報出錯誤信息decr num
--> 如果num不存在初始化為0然后減1,num變?yōu)?1
--> 如果num存在并且可以轉(zhuǎn)為整形奉呛,num直接減1
--> 如果num存在但是不能轉(zhuǎn)為整形夯尽,報出錯誤信息
- 擴展命令
incrby num increment
--> 如果num不存在初始化為0然后減increment
--> 如果num存在并且可以轉(zhuǎn)為整形匙握,num直接減increment
--> 如果num存在但是不能轉(zhuǎn)為整形圈纺,報出錯誤信息decrby num decrement
--> 如果num不存在初始化為0然后減decrement
--> 如果num存在并且可以轉(zhuǎn)為整形,num直接減decrement
--> 如果num存在但是不能轉(zhuǎn)為整形灯谣,報出錯誤信息append num value
--> 如果num不存在新創(chuàng)建一個num value
--> 如果num存在胎许,以字符串形式在num后面追加一個value罗售,得到追加之后的長度,結(jié)果是"numvalue"
存儲Hash
hash類型可以看做是String key 和String value的map容器谬擦,非常適合存儲值對象的信息惨远,比如同戶名话肖,密碼最筒,年齡等...
存儲hash常用的命令:
- 賦值
hset myset key value
--> 設(shè)置 myset 指定的哈希集中指定字段key的值。
--> 如果 myset 指定的哈希集不存在辙培,會創(chuàng)建一個新的哈希集并與 myset 關(guān)聯(lián)扬蕊。
--> 如果字段在哈希集中存在,它將被重寫hmset myset key value [key value ...]
--> 設(shè)置 myset 指定的哈希集中指定字段的值歇父。該命令將重寫所有在哈希集中存在的字段
--> 如果 myset 指定的哈希集不存在再愈,會創(chuàng)建一個新的哈希集并與 myset 關(guān)聯(lián)
- 取值
hget myset key
--> 返回 myset 指定的哈希集中該key所關(guān)聯(lián)的值hmget myset key [key ...]
--> 設(shè)置 myset 指定的哈希集中指定key的值翎冲。該命令將重寫所有在哈希集中存在的字段府适。
--> 如果 myset 指定的哈希集不存在,會創(chuàng)建一個新的哈希集并與 myset 關(guān)聯(lián)hgetall myset
--> 返回 key 指定的哈希集中所有的字段和值。返回值中疟暖,每個字段名的下一個是它的值田柔,所以返回值的長度是哈希集大小的兩倍
- 刪除
hdel myset key [key ...]
--> 從 key 指定的哈希集中移除指定的域硬爆。在哈希集中不存在的域?qū)⒈缓雎?br> --> 如果 key 指定的哈希集不存在缀磕,它將被認為是一個空的哈希集,該命令將返回0del myset
--> 直接刪除整個哈希集
- 增加數(shù)字
- hincreby myhash key increment
增加 myhash 指定的哈希集中指定字段的數(shù)值糟把。如果 myhash不存在遣疯,會創(chuàng)建一個新的哈希集并與 myhash 關(guān)聯(lián)凿傅。如果字段不存在,則字段的值在該操作執(zhí)行前被設(shè)置為 0
HINCRBY 支持的值的范圍限定在 64位 有符號整數(shù)
- 自學(xué)命令
hexists myhash key
判斷key是否在myhash中存在文判。存在返回1室梅,否則返回0hlen myhash
返回 myhash 指定的哈希集包含的字段的數(shù)量亡鼠。hkeys myhash
返回 myhash 指定的哈希集中所有字段的key。hvals myhash
返回 myhash 指定的哈希集中所有字段的value仁热。
存儲list:
- ArrayList使用數(shù)字方式存儲
- LinkedList使用雙向鏈表方式存儲
- 雙向鏈表中增加數(shù)據(jù)
- 雙向鏈表中刪除數(shù)據(jù)
存儲list常用的命令:
- 兩端添加
- lpush
- rpush
- 查看鏈表
- lrange
- 兩端彈出
- lpop
- rpop
- 獲取列表元素個數(shù)
- llen
- 擴展命令
- lpushx
- rpushx
- lrem
- lset
- linsert
- rpoplpush --> 消息隊列
存儲Set
- 和list類型不同的是抗蠢,Set集合中不允許出現(xiàn)重復(fù)的元素
- Set可以包含的元素數(shù)量是4294967295
存儲Set常用的命令:
- 添加刪除元素
- sadd myset 1 2 3
- srem myset 2
- 獲取集合中的元素
- smembers myset --> 獲取所有元素
- sismember myset 3 -> 判斷某個元素時候?qū)儆诩?/li>
- 集合中的差集運算
- sdiff
- 集合中的并集運算
- sunion
- 集合中的交集運算
- sinter
- 擴展命令
- scard -> 獲取元素個數(shù)
- srandmember myset -> 隨機返回myset中的某個成員
- sdiffstore my1 my2 my3-> 把my2 my3差集存在my1中
- sinterstore my1 my2 my3 -> 把my2 my3 交集存在my1中
- sunionstore my1 my2 my3 -> 把my2 my3 并集存入my1中
存儲Set使用的場景
- 跟蹤一些唯一性數(shù)據(jù)
- 用于維護數(shù)據(jù)對象之間的關(guān)聯(lián)關(guān)系,可以做一些并集交集的運算
存儲Sorted-Set
- 與Set的區(qū)別:
- Sorted-Set成員有序秽褒,時間復(fù)雜度是元素個數(shù)的對數(shù)O(logn)
- Sorted-Set中的成員在集合中的位置是有序的
存儲Sorted-Set常用的命令:
- 添加元素
- zadd mysort 50 funi 60 sorw
- 刪除元素
- zrem mysort funi sorw -> 刪除sorted-set中的funi sorw記錄
- 獲取元素
- zscore mysort funi -> 獲取具體元素的分數(shù)
- zcard mysort -> 獲取mysort的元素個數(shù)
- 范圍查詢
- zrange mysort 0 -1 -> 顯示所有元素(不顯示分數(shù))
- zrange mysort 0 -1 withscores -> 顯示所有元素并顯示分數(shù)销斟,由小到大排序
- zrevrange mysort 0 -1 withscores -> 顯示所有元素并顯示分數(shù)椒舵,由大到小排序
- zremrangebyrank mysort 0 4 -> 按照下標順序刪除元素
- zremrangebyscore mysort 80 100 -> 按照分數(shù)的范圍刪除元素
- 擴展命令
- zrangebyscore mysort 0 100 [withscores][limit 0 2]-> 顯示分數(shù)為0到100并按照從小到大排序顯示,withscore顯示分數(shù),limit顯示從第0個到第2個
- zincrby mysort 3 li -> 給li的分數(shù)加3
- zcount mysort 80 90 -> 顯示分數(shù)是80到90的元素個數(shù)
Sorted-Set使用場景
- 大型在線游戲積分排行榜
先使用zadd添加笔宿,然后zrange獲取 - 構(gòu)建索引數(shù)據(jù)
Keys的通用操作
- keys * -> 獲取所有的key
- del -> 刪除key
- exists -> 判斷是否存在
- get key -> 獲取這個key的value
- rename company newcompany -> 重命名company
- expire newcompany 1000 -> 設(shè)置1000s的過期時間
- ttl newcompany -> 過期時間剩余
- type key -> 獲取這個key的數(shù)據(jù)類型
Redis特性:
- 多數(shù)據(jù)庫
- 一個redis實例最多可以提供十六個數(shù)據(jù)庫措伐,就像是mysql的數(shù)據(jù)庫一樣侥加,客戶端可以指定連接那個數(shù)據(jù)庫,redis的數(shù)據(jù)庫下標是從0 - 15昔穴。
- 可以使用select 1 -> 來選擇幾號數(shù)據(jù)庫吗货。默認使用的是0號數(shù)據(jù)庫
- 可以使用move myset 1 -> 將myset移動到1號數(shù)據(jù)庫
- 支持事務(wù)
Redis使用multi exec discard來執(zhí)行事務(wù),事務(wù)中所有的命令都會被串行化執(zhí)行笨腥,事務(wù)執(zhí)行期間勇垛,redis不會為其他客戶端提供服務(wù)闲孤,保證事務(wù)的原子性。與關(guān)系型數(shù)據(jù)庫不同的是肥照,redis事務(wù)中舆绎,如果某個命令執(zhí)行失敗决摧,事務(wù)不會終止掌桩,而是繼續(xù)執(zhí)行后面的命令
- 可以使用multi 來開啟是一個事務(wù) 相當于start transaction
- 通過exec相當于提交 相當于commit
- 通過discard相當于回滾 相當于roolback
Redis的持久化
- Redis的高效率源于Redis把數(shù)據(jù)都存儲在內(nèi)存當中波岛,為了保證Redis在服務(wù)重啟之后數(shù)據(jù)不丟失,就需要把Redis中的數(shù)據(jù)進行持久化(數(shù)據(jù)從內(nèi)存同步到硬盤)音半。
持久化方式:
- RDB方式
- AOF方式
持久化使用的方式:
RDB方式
默認支持的则拷,不需要設(shè)置。RDB方式就是在默認的時間間隔之后曹鸠,將內(nèi)存中的數(shù)據(jù)集快照寫入到磁盤
AOF方式:
以日志的方式記錄服務(wù)器所處理的每一個操作煌茬,在Redis服務(wù)器啟動之初,會讀取這個文件彻桃,然后重新構(gòu)建坛善,保證數(shù)據(jù)是完整的
無持久化:
通過配置禁用Redis持久化功能,這個時候Redis就是一個緩存的功能
同時使用RDB和AOF的方式:’
數(shù)據(jù)集快照+日志
Redis持久化的RDB方式
優(yōu)勢:
- 只有一個文件,對于文件備份而言很簡單眠屎。
- 災(zāi)難恢復(fù),RDB可以壓縮文件之后轉(zhuǎn)移個另一個服務(wù)器上
- 性能最大化改衩,分叉出一些子進程岖常,然后使用子進程來做持久化操作,可以極大的避免IO的影響
- 相比于AOF如果數(shù)據(jù)集很大葫督,啟動效率更高
劣勢:
- 如果想保證數(shù)據(jù)的高可用性竭鞍,是數(shù)據(jù)盡可能的不丟失RDB不是很好的選擇,因為如果在系統(tǒng)定時持久化之前宕機橄镜,還沒有來得及寫數(shù)據(jù)偎快,就會導(dǎo)致數(shù)據(jù)的丟失
- 由于RDB使用fork分叉來使用子進程完成數(shù)據(jù)的持久化操作,因此如果數(shù)據(jù)集很大蛉鹿,會導(dǎo)致整個服務(wù)器停止幾百毫秒來等待持久化操作的完成滨砍。
配置:redis.conf
save 900 1 //表示每900s有一個key發(fā)生變化就會之久化一次
save 300 10 //每300s有10個key發(fā)生變化,會往硬盤上寫一次
save 60 10000 //每60s有10000個key發(fā)生變化會寫一次
保存在./dump.rdb
Redis持久化的AOF方式
優(yōu)勢:
- 更高的數(shù)據(jù)安全性妖异。redis中提供了三種同步策略:每秒同步惋戏,每修改同步,和不同步他膳;
- 對日志寫入的過程是append追加的模式响逢。因此就算宕機,也不會破壞已經(jīng)寫入的日志棕孙。如果寫入一半的時候出現(xiàn)問題舔亭,也可以使用redis-cheak-aof這個工具來幫助我們解決數(shù)據(jù)一致性的問題
- 如果日志過大,redis會自動啟動數(shù)據(jù)重寫機制蟀俊,以append的模式不斷的寫入老的磁盤文件當中钦铺,同時redis還會產(chǎn)生一個文件來記錄此期間產(chǎn)生的修改命令。因此重寫切換的時候還是可以保證數(shù)據(jù)的安全性肢预。
- AOF包含的是格式清晰的日志文件矛洞,用于記錄所有的修改操作。甚至可以通過這個文件來重建數(shù)據(jù)
劣勢:
- AOF的文件比RDB的文件更大
- 同步策略的不同導(dǎo)致AOF運行的效率低于RDB
配置:redis.conf
appendonly no //默認不啟動AOF
appendonly.aof //AOF文件
//同步方式:
# appendfsync always //每修改同步
# appendfsync everysec //每秒同步
# appendfsync no //不同步
如果要使用AOF方式烫映,應(yīng)該首先修改第1行的appendonly 為yes沼本;然后appendfsync為always保證數(shù)據(jù)的安全
參考:
https://github.com/xetorthio/jedis
https://redis.io/
https://redis.io/documentation
http://www.redis.cn/commands.html
https://www.imooc.com/learn/839