###前言redis
昨天和室友去包夜,玩了一夜的
LOL
,跪了一整夜,可是很開心。從S1
末開始玩LOL
的我,到如今仍是青銅,真是菜的摳腳。最近負能力滿滿的,惟有睡覺和學習纔可解憂愁。今天也看了慕課網上面的《Redis
入門》,來記一下學習筆記。(寫這篇文章開頭的時候應該是一個星期以前)算法
###NoSQL概述shell
NoSQL
就是Not Only SQL
的意思,是非關係型數據庫。數據庫
爲何須要NoSQL
?vim
High performance
- 高併發讀寫數組
Huge Storage
- 海量數據的高效率存儲和訪問緩存
High Scalability & High Availability
- 高可擴展性和高可用性安全
NoSQL數據庫的四大分類bash
鍵值(Key - Value
)存儲:優勢是快速查詢,缺點存儲的數據缺乏結構化。服務器
列存儲:優勢是查詢比較快,擴展性比較強,缺點是功能相對侷限。
文檔數據庫:對應的產品就是MongoDB
。對數據結構要求不是特別嚴格,查詢性能不能特別高,缺乏統一查詢的語法。
圖形數據庫:優勢是利用圖結構相關的算法,缺點是須要對整個圖進行結算才能得出結果,不能做爲分佈式的解決方案。
NoSQL
的特色,美滋滋。
###Redis的概述
高性能鍵值對數據庫,支持的鍵值數據類型:
字符串類型 - String
列表類型 - Set
有序集合類型 - Sorted Set
散列類型 - Hash
集合類型 - List
Redis
的應用場景
緩存
任務隊列
網站訪問統計
應用排行榜
分佈式集羣架構中的session分離
###Redis在Linux上的使用 能夠看我這篇文章【Linux學習】 Redis經常使用的一些指令
###Jedis的入門
Java
平臺上使用redis
,確定須要Jedis
這個客戶端。首先在pom
文件中引入Jedis
的依賴<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
複製代碼
public void methodOne() {
Jedis jedis = new Jedis("100.64.84.47", 6379);
jedis.set("name", "cmazxiaoma");
String value = jedis.get("name");
System.out.println(value);
jedis.close();
}
複製代碼
public void methodTwo() {
//得到鏈接池的配置對象
JedisPoolConfig config = new JedisPoolConfig();
//設置最大鏈接數
config.setMaxTotal(30);
//設置最大空閒鏈接數
config.setMaxIdle(10);
//得到鏈接池
JedisPool jedisPool = new JedisPool(config, "100.64.84.47", 6379);
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
String value = jedis.get("name");
System.out.println(value);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (jedis != null) {
jedis.close();
}
jedisPool.close();
}
}
}
複製代碼
public class JedisDemo1Test {
private JedisDemo1 demo;
@Before
public void setUp() {
demo = new JedisDemo1();
}
@Test
public void methodOne() throws Exception {
demo.methodOne();
}
@Test
public void methodTwo() throws Exception {
demo.methodTwo();
}
}
複製代碼
運行Test Case
,測試成功。
咱們在Xshell
軟件,輸入get name
指令,也能夠看到輸出cmazxiaoma
。
###Redis的數據結構
####String
Key
定義的注意點:
存儲String
:
Value
最多能夠容納的數據長度是512M
。存儲String
經常使用的命令:
賦值
取值
刪除
數值增減
若是屬性不存在的話,那麼integer
類型默認爲0
。
若是name
屬性的值不能轉換成integer
類型,那麼會拋出ERR is not an integer or out of range
異常。
decr
指令也是同樣的。
incrby
、decrby
也是同樣的,很簡單。
append
指令能夠拼接字符串。
若是append key cmazxiaoma
。這個key
不存在的話,首先會建立這個key
,而後存入cmazxiaoma
內容,接着輸出cmazxiaoma
。
####Hash
賦值,可使用hset myhash key value
單一賦值、hmset myhash key value key value
屢次賦值。
取值,能夠用hget myhash key
單一取值、hmget myhash key key
多個取值、hgetall
取出全部key
所對應的值。
刪除 ,能夠用hdel myhash key
刪除單一的key
。
hdel myhash key key
刪除多個的key
。
del myhash
刪除myhash
中全部的key
。
數值增減,hincrby myhash key 100
使用hexists myhash key
判斷key
是否在myhash
中存在,存在返回1
,不存在返回0
。
hlen myhash
獲取myhash
中存在key
的數量。
hkeys myhash
獲取myhash
中全部的key
。
hvals myhash
獲取myhash
中全部的values
。
####List
存儲list:
ArrayList
使用數組方式LinkedList
使用雙向鏈表方式兩端添加
lpush a b c
命令在左端添加,那麼c
確定是在最左端。
rpush a b c
命令在右端添加,那麼c
確定是在最右端。
兩端彈出
lpop mylist
彈出mylist
中頭部元素、rpop mylist2
彈出mylist2
尾部中的元素。它們都是3
。
mylist
、mylist2
。
查看列表
lrange mylist 0 5
來查看mylist
列表,mylist
插入的方式從頭結點開始添加的,那麼輸出確定是321abc
。
lrange mylist2 0 5
查看mylist2
列表,mylist2
插入的方式是從最右端添加的,那麼輸出確定是abc123
獲取列表元素的個數
llen mylist
命令
擴展命令
使用lpushx mylist x
,使插入的元素在頭部位置。
使用rpushx mylist x
,使插入的元素在尾部位置。
使用lrem mylist count element
,count
表明是刪除的次數,element
表明是須要刪除的元素。若是count > 0
表明刪除的方式從頭至尾,刪除count
個element
,count < 0
表明刪除的方式從尾到頭,刪除count
個element
。若是count = 0
,刪除mylist
中全部和element
相同的元素。
lrem mylist 2 test1
lrem mylist -2 test1
lrem mylist 0 cmazxiaoma
在某一個下標位置插入元素。lset mylist index element
在目標元素以前插入指定的元素。linsert mylist before helloworl before_helloworld
在目標元素以後插入指定的元素。linsert mylist helloworld after after_helloworld
彈出mylist
中最後一個元素,並插入到mylist
中的頭部。rpoplpush mylist mylist
rpoplpush
使用場景
####Set 和List
類型不一樣的是,Set
集合中不容許出現重複的元素。
添加/刪除元素
sadd myset a b c
,若是咱們重複添加相同的元素,確定是不成功的。好比sadd myset a
。
srem myset a
,刪除myset
中的a
元素。
myset
中的元素。smembers myset
myset
中的成員。sismember myset a
,返回0
表明不存在,返回1
表明存在。
得到集合中的元素, smembers myset
集合中的差集運算,sdiff myset2 myset
。myset2
中元素有b,c,d
。myset
中元素有b,c
。它們之間的差集運算結果應該爲d
。
集合中的交集運算,sinter myset2 myset
,應該輸出cb
。
集合中的並集運算,sunion myset2 myse
t,應該輸出cbd
。
擴展命令
scard myset
查看myset
有多少個元素。
srandmember myset
隨機返回myset
中的一個元素。
sdiffstore new_myset myset2 myset
把myset
和myset2
差集元素的結果存儲到new_myset
中。(sinterstore
, sunionstore
也是同樣的用法)
Set使用場景
####SortedSet SortedSet
中的成員在集合中的位置是有序的。
添加元素 zadd mysort 70 cmazxiaoma 80 xiaoma 100 doudou
得到元素
zcard mysort
得到mysort
中全部元素的個數
得到mysort
中name
爲cmazxiaoma
對應的成績。zscore mysort cmazxiaoma
刪除元素,zrem mysort cmazxiaoma deli doudou xiaoma
範圍查詢 zrange mysort 0 -1
,輸出的key
是按成績正序排列。
若是輸出的數據項要帶上成績的話,指令應該是zrange mysort 0 -1 withscores
若是輸出的數據項想按成績逆序排序,那麼就應該zrevrange mysort 0 -1 withscores
若是想按排名範圍進行刪除的話,那麼應該zremrangebyrank mysort 0 2
若是想按成績範圍進行刪除的話,那麼應該zremrangebyscore mysort 0 10
。顧名思義刪除成績在0-10
以內的數據項。
擴展命令
查看分數在0-10
以內的學生信息,zrangebyscore mysort 0 10 withscores
查看分數在0-100
以內且在第1
行-第2
行的學生信息。zrangebyscore mysort 0 100 withiscores limit 0 2
給cmazxiaoma
的成績加100
分。zincrby mysort cmazxiaoma 100
查當作績0-10
之間的學生的個數。zcount mysort 0 10
Sorted Set
使用場景
如大型在線遊戲積分排行榜
構建索引數據
###Redis中的通用命令
key *
獲取全部redis中的key
keys my*
獲取全部redis
中以my
開頭的key
exists mylist
查看redis
中是否存在mylis
t,0
表明不存在,1
表明存在。
rename name new_name
給名字爲name
的數據結構重命名爲new_name
expire new_name 10
設置redis
中new_name
過時時間,經過ttl new_name
看到其距離過時的時間。
type mylist
,能夠查看mylist
對應的數據結構類型。
###Redis的事務
Redis
相關的特性:
多數據庫
Redis
事務
一個Redis
最多能夠提供16
個數據庫,下標分別是0-15
。客戶端默認鏈接的是第0
號數據。咱們能夠經過select index
來選擇數據庫。
咱們想把第0
號的數據庫中某些key
移動到第1
號數據庫裏面,那麼咱們該怎麼作呢。經過move cmazxiaoma_test_mayday_5 1
就能夠完成。
咱們能夠經過multi
、exec
、discard
來完成事務操做。事務執行期間,Redis
不會爲其餘客戶端提供任何服務,以保證事務中的全部命令原子執行。multi
至關於開啓事務,exec
至關於提交,discard
至關於回滾。
首先咱們在第一個客戶端進行以下操做。咱們在第一個客戶端開啓了事務,在事務中咱們incr num
2
次,按理來講,get num
應該等於4
。
咱們在第二個客戶端輸入get num
,發現num
仍是2
。那麼證實了咱們的結論:事務執行期間,Redis
不會爲其餘客戶端提供任何服務,以保證事務中的全部命令原子執行。
若是咱們在第一個客戶端提交了事務。
接着咱們在第二個客戶端get num
,發現能夠num
的值獲得了更新。
咱們能夠演示一下回滾操做,首先set user cmazxiaoma
,接着開啓事務,在事務中set user xiaoma
,而後進行回滾操做,發現 get user
依然是cmazxiaoma
。
###Redis的持久化 Redis
的性能體如今它把數據都保存在內存當中。咱們把內存中的數據同步到硬盤當中的操做稱之爲持久化。
Redis
持久化方式:
RDB
方式,在指定的時間內,把內存中的數據快照寫入到硬盤當中。
AOF
方式,將以日誌的形式記錄服務器所處理的每個操做。當Redis
服務器啓動之初,它會讀取該aof
文件,會從新構建咱們的數據庫。保證咱們啓動以後,保證數據的完整性。
無持久化,咱們能夠經過配置禁止Redis
服務器的持久化,咱們認爲Redis
就是緩存的一種機制了。
同時使用。
RDB
:
默認狀況下,每隔一段時間redis
服務器程序會自動對數據庫作一次遍歷,把內存快照寫在一個叫作"dump.rdb"
的文件裏,這個持久化機制叫作SNAPSHOT
。有了SNAPSHOT
後,若是服務器宕機,從新啓動redis
服務器時,redis
會自動加載"dump.rdb"
,將數據庫狀態恢復上一次SNAPSHOT
的狀態。
Redis
服務器初始化過程當中,設定了定時時間,每隔一段時間就會觸發持久化操做,進入定時事件處理程序中,就會fork
出子進程來進行持久化操做。
Redis
服務器預設了save
指令,客戶端可要求服務器進程中斷服務,執行持久化操做。
咱們能夠經過vim /etc/redis.conf
打開配置文件,能夠看到如下配置。
同時咱們還能夠看到內存快照輸出在file
文件名。
優缺點:
若是數據集很大,RDB
相對於AOF
啓動效率很更高。
若是想保證數據的高可用性,最大限度的避免數據的丟失,RDB
將不是一個好的選擇。由於系統在定時持久化操做以前,還沒來得及在硬盤寫入數據就發生宕機的話,就形成了數據的丟失。
RDB
經過fork
出子線程來完成數據持久化操做,若是當數據集很大的時候,可能會致使服務器中止幾百ms
,或者幾s
。
AOF
(append only file
):
對於Redis
服務器而言,其缺省的機制是RDB
,若是須要使用AOF
,則須要修改appendonly no
改爲appendonly yes
。Redis
在每一次收到數據修改的命令以後,都會將其追加到AOF
文件中。在Redis
下一次從新啓動時,須要加載AOF
文件中的信息來構建最新的數據到內存中。
能夠記錄服務器的全部寫操做。在服務器從新啓動時,會把全部的寫操做從新執行一遍從而實現數據的備份。當寫操做集過大(比原有的數據集還大),Redis
會重寫寫操做集。
帶來更好的數據安全性,有3
種同步策略,每秒同步,每修改同步,不一樣步。 每秒同步也是異步完成的,效率也很是高。缺點是一旦系統發生宕機的現象,那麼這一秒中的修改的數據就會發生丟失。每修改同步,咱們能夠視爲同步持久化。每一次發生數據的變化,就會當即的記錄在磁盤,這種效率很低,可是很安全。
採用append
追加的模式,就算系統發生宕機,也不會影響咱們日誌文件中已經存在的內容。然而咱們本次操做中,只寫入了一半數據就出現了系統崩潰的問題。在Redis下一次啓動以前,咱們能夠經過"redis-check-aof --fix <filename>"
命令來修復壞損的AOF
文件,解決數據一致性的問題。
對於相同數量的數據集而言,AOF
文件一般要大於RDB
文件。
AOF
在運行效率上每每會慢於RDB
。
RDB
和AOF
的區別 前者是保存了數據自己,然後者是記錄了數據的變動。###尾言
這篇文章最後在網吧完成的,勿以善小而不爲。