Not-Only SQL,泛指 非關係型數據庫,爲了解決高併發、高拓展、高可用、大數據存儲問題 產生的數據庫解決方案。
相關產品:Tokyo Cabinet/Tyrant、==Redis==、Voldemort、Berkeley DBhtml
典型應用:內容緩存,主要用於處理大量數據的高訪問負載。java
數據模型: 一系列鍵值對redis
優點: 快速查詢算法
劣勢: 存儲的數據缺乏結構化spring
相關產品: Cassandra, HBase, Riaksql
典型應用: 分佈式的文件系統數據庫
**數據模型:** 以列簇式存儲,將同一列數據存在一塊兒
優點: 查找速度快,可擴展性強,更容易進行分佈式擴展數組
劣勢: 功能相對侷限緩存
相關產品: CouchDB、MongoDB服務器
典型應用: Web應用(與Key-Value相似,Value是結構化的)
數據模型: 一系列鍵值對
優點: 數據結構要求不嚴格
劣勢: 查詢性能不高,並且缺少統一的查詢語法
相關產品:Neo4J、InfoGrid、Infinite Graph
典型應用: 社交網絡
數據模型: 圖結構
優點: 利用圖結構相關算法。
劣勢: 須要對整個圖作計算才能得出結果,不容易作分佈式的集羣方案。
C語言開發;
支持5種鍵值數據類型:字符串類型, 散列類型, 列表類型, 集合類型, 有序集合類型.
Redis 支持不少特性,例如將內存中的數據持久化到硬盤中,使用複製來擴展讀性能,使用分片來擴展寫性能。
數據查詢、短鏈接、新聞內容、商品內容等等。(最多使用)
分佈式集羣架構中的session分離。
(秒殺、搶購、12306等等)
聊天室的在線好友列表。
應用排行榜。
網站訪問統計。
數據過時處理(能夠精確到毫秒)
默認端口是6379
遠程鏈接redis服務,須要關閉或者修改防火牆配置。
默認一共是16個數據庫,每一個數據庫之間是相互隔離。數據庫的數量是在redis.conf中配置的。
切換數據庫使用命令:select 數據庫編號 例如:select 1
java客戶端有 Jedis、Redisson、Jredis、JDBC-Redis等
@Test public void testJedis() { //建立一個Jedis的鏈接 Jedis jedis = new Jedis("127.0.0.1", 6379); //執行redis命令 jedis.set("mytest", "hello world, this is jedis client!"); //從redis中取值 String result = jedis.get("mytest"); //打印結果 System.out.println(result); //關閉鏈接 jedis.close(); }
@Test public void testJedisPool() { //建立一鏈接池對象 JedisPool jedisPool = new JedisPool("127.0.0.1", 6379); //從鏈接池中得到鏈接 Jedis jedis = jedisPool.getResource(); String result = jedis.get("mytest"); System.out.println(result); //關閉鏈接 jedis.close(); //關閉鏈接池 jedisPool.close(); }
配置文件, application.xml
<!-- 鏈接池配置 --> <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig"> <!-- 最大鏈接數 --> <property name="maxTotal" value="30" /> <!-- 最大空閒鏈接數 --> <property name="maxIdle" value="10" /> <!-- 每次釋放鏈接的最大數目 --> <property name="numTestsPerEvictionRun" value="1024" /> <!-- 釋放鏈接的掃描間隔(毫秒) --> <property name="timeBetweenEvictionRunsMillis" value="30000" /> <!-- 鏈接最小空閒時間 --> <property name="minEvictableIdleTimeMillis" value="1800000" /> <!-- 鏈接空閒多久後釋放, 當空閒時間>該值 且 空閒鏈接>最大空閒鏈接數 時直接釋放 --> <property name="softMinEvictableIdleTimeMillis" value="10000" /> <!-- 獲取鏈接時的最大等待毫秒數,小於零:阻塞不肯定的時間,默認-1 --> <property name="maxWaitMillis" value="1500" /> <!-- 在獲取鏈接的時候檢查有效性, 默認false --> <property name="testOnBorrow" value="false" /> <!-- 在空閒時檢查有效性, 默認false --> <property name="testWhileIdle" value="true" /> <!-- 鏈接耗盡時是否阻塞, false報異常,ture阻塞直到超時, 默認true --> <property name="blockWhenExhausted" value="false" /> </bean> <!-- redis單機 經過鏈接池 --> <bean id="jedisPool" class="redis.clients.jedis.JedisPool" destroy-method="close"> <constructor-arg name="poolConfig" ref="jedisPoolConfig" /> <constructor-arg name="host" value="192.168.242.130" /> <constructor-arg name="port" value="6379" /> </bean>
測試代碼:
@Test public void testJedisPool() { JedisPool pool = (JedisPool) applicationContext.getBean("jedisPool"); Jedis jedis = null; try { jedis = pool.getResource(); jedis.set("name", "lisi"); String name = jedis.get("name"); System.out.println(name); } catch (Exception ex) { ex.printStackTrace(); } finally { if (jedis != null) { // 關閉鏈接 jedis.close(); } } }
Redis命令:http://www.redis.cn/commands.html#
注意:
?
==
單組 SET key value
多組 mset k1 v1 k2 v2 k3 v3
單組 GET key
多組 mget k1 k3
getset s2 222
DEL key
當存儲的字符串是整數時,Redis提供了一個實用的命令INCR,其做用是讓當前鍵值遞增 1,並返回遞增後的值:INCR
key。 eg:incr num
增長指定的整數 :INCRBY
key increment 。 eg: incrby num 2
遞減數值:DECR
key。 eg:decr num
減小指定的整數:DECRBY
key decrement。 eg:decrby num 3
APPEND
APPEND的做用是向鍵值的末尾追加value。若是鍵不存在則將該鍵的值設置爲value,即至關於 SET key value。返回值是追加後字符串的總長度。
語法:APPEND key value 127.0.0.1:6379> set str hello OK 127.0.0.1:6379> append str " world!" (integer) 12 127.0.0.1:6379> get str "hello world!"
STRLEN
STRLEN命令返回鍵值的長度,若是鍵不存在則返回0。
語法:STRLEN key 127.0.0.1:6379> strlen str (integer) 0 127.0.0.1:6379> set str hello OK 127.0.0.1:6379> strlen str (integer) 5
假設有User對象以JSON序列化的形式存儲到Redis中,User對象有id,username、password、age、name等屬性,
若是在業務上只是更新age屬性, 若是仍然採用上邊的方法在傳輸、處理時會形成資源浪費,hash能夠很好的解決這個問題。它提供了字段和字段值的映射。字段值只能是字符串類型,不支持散列類型、集合類型等其它類型。
HSET命令不區分插入和更新操做,當執行插入操做時HSET命令返回1,當執行更新操做時返回0。返回值爲行數
1. 一次只能設置一個字段值 語法:HSET key field value 127.0.0.1:6379> hset user username zhangsan (integer) 1 2. 一次能夠設置多個字段值 語法:HMSET key field value [field value ...] 127.0.0.1:6379> hmset user age 20 username lisi OK
1. 一次只能獲取一個字段值 語法:HGET key field 127.0.0.1:6379> hget user username "zhangsan「 2. 一次能夠獲取多個字段值 語法:HMGET key field [field ...] 127.0.0.1:6379> hmget user age username "20" "lisi" 3. 獲取全部字段值 語法:HGETALL key 127.0.0.1:6379> hgetall user "age" "20" "username" "lisi"
能夠刪除一個或多個字段,返回值是被刪除的字段個數
語法:HDEL key field [field ...] 127.0.0.1:6379> hdel user age (integer) 1 127.0.0.1:6379> hdel user age name (integer) 0 127.0.0.1:6379> hdel user age username (integer) 1
語法:HINCRBY key field increment 127.0.0.1:6379> hincrby user age 2 將用戶的年齡加2 (integer) 22 127.0.0.1:6379> hget user age 獲取用戶的年齡 "22「
hkeys獲取字段名,即key
hvals獲取字段值,即value
語法: HKEYS key HVALS key 127.0.0.1:6379> hmset user age 20 name lisi OK 127.0.0.1:6379> hkeys user "age" "name" 127.0.0.1:6379> hvals user "20" "lisi"
語法:HLEN key 127.0.0.1:6379> hlen user (integer) 2
ArrayList與LinkedList的區別
ArrayList使用數組方式存儲數據,因此根據索引查詢數據速度快,而新增或者刪除元素時須要設計到位移操做,因此比較慢。
LinkedList使用雙向鏈表方式存儲數據,每一個元素都記錄先後元素的指針,因此插入、刪除數據時只是更改先後元素的指針指向便可,速度很是快。而後經過下標查詢元素時須要從頭開始索引,因此比較慢,可是若是查詢前幾個元素或後幾個元素速度比較快。
左追加:lpush
語法:LPUSH key value [value ...] 127.0.0.1:6379> lpush list:1 1 2 3 (integer) 3
右追加:rpush
語法:RPUSH key value [value ...] 127.0.0.1:6379> rpush list:1 4 5 6 (integer) 3
左彈出:lpop
右彈出:rpop
語法: LPOP key RPOP key 127.0.0.1:6379> lpop list:1 "3「 127.0.0.1:6379> rpop list:1 "6「
LRANGE命令是獲取列表中的某一片斷,將返回start、stop之間的全部元素(包含兩端的元素即閉區間)。
索引從0開始。索引能夠是負數,如:「-1」表明最後邊的一個元素。
語法:LRANGE key start stop 127.0.0.1:6379> lrange list:1 0 2 "2" "1" "4"
語法:LLEN key 127.0.0.1:6379> llen list:1 (integer) 2
語法:LREM key count value
1. 得到指定索引的元素值 語法:LINDEX key index 127.0.0.1:6379> lindex l:list 2 "1" 2. 設置指定索引的元素值 語法:LSET key index value 127.0.0.1:6379> lset l:list 2 2 OK 127.0.0.1:6379> lrange l:list 0 -1 "6" "5" "2" "2"
語法:LTRIM key start stop 閉區間 127.0.0.1:6379> lrange l:list 0 -1 "6" "5" "0" "2" 127.0.0.1:6379> ltrim l:list 0 2 OK 127.0.0.1:6379> lrange l:list 0 -1 "6" "5" "0"
該命令首先會在列表中從左到右查找值爲pivot的元素,而後根據第二個參數是BEFORE仍是AFTER來決定將value插入到該元素的前面仍是後面。
語法:LINSERT key BEFORE|AFTER pivot value 127.0.0.1:6379> lrange list 0 -1 "3" "2" "1" 127.0.0.1:6379> linsert list after 3 4 (integer) 4 127.0.0.1:6379> lrange list 0 -1 "3" "4" "2" "1"
語法:RPOPLPUSH source destination 127.0.0.1:6379> rpoplpush list newlist "1" 127.0.0.1:6379> lrange newlist 0 -1 "1" 127.0.0.1:6379> lrange list 0 -1 "3" "4" "2"
語法:SADD key member [member ...] 127.0.0.1:6379> sadd set a b c (integer) 3 127.0.0.1:6379> sadd set a (integer) 0 語法:SREM key member [member ...] 127.0.0.1:6379> srem set c d (integer) 1
語法:SMEMBERS key 127.0.0.1:6379> smembers set "b" "a」
語法:SISMEMBER key member 127.0.0.1:6379> sismember set a (integer) 1 127.0.0.1:6379> sismember set h (integer) 0
差集運算 A-B [ sdiff]:屬於A而且不屬於B的元素構成的集合。
語法:SDIFF key [key ...] 127.0.0.1:6379> sadd setA 1 2 3 (integer) 3 127.0.0.1:6379> sadd setB 2 3 4 (integer) 3 127.0.0.1:6379> sdiff setA setB "1" 127.0.0.1:6379> sdiff setB setA "4"
交集運算 A ∩ B [ sinter ]:屬於A且屬於B的元素構成的集合。
語法:SINTER key [key ...] 127.0.0.1:6379> sinter setA setB "2" "3"
並集運算 A ∪ B [ sunion ]: 屬於A或者屬於B的元素構成的集合
語法:SUNION key [key ...] 127.0.0.1:6379> sunion setA setB "1" "2" "3" "4"
scard
語法:SCARD key 127.0.0.1:6379> smembers setA "1" "2" "3" 127.0.0.1:6379> scard setA (integer) 3
注意:因爲集合是無序的,全部SPOP命令會從集合中隨機選擇一個元素彈出
語法:SPOP key 127.0.0.1:6379> spop setA "1「
在集合類型的基礎上,有序集合類型爲集合中的每一個元素都關聯一個分數,這使得咱們不只能夠完成插入、刪除和判斷元素是否存在在集合中,還可以得到分數最高或最低的前N個元素、獲取指定分數範圍內的元素等與分數有關的操做。但更耗內存。
向有序集合中加入一個元素和該元素的分數,若是該元素已經存在則會用新的分數替換原有的分數。返回值是新加入到集合中的元素個數,不包含以前已經存在的元素。
語法:ZADD key score member [score member ...] 127.0.0.1:6379> zadd scoreboard 80 zhangsan 89 lisi 94 wangwu (integer) 3 127.0.0.1:6379> zadd scoreboard 97 lisi (integer) 0
語法:ZSCORE key member 127.0.0.1:6379> zscore scoreboard lisi "97"
移除有序集key中的一個或多個成員,不存在的成員將被忽略。
當key存在但不是有序集類型時,返回一個錯誤。
語法:ZREM key member [member ...] 127.0.0.1:6379> zrem scoreboard lisi (integer) 1
從小到大的順序:zrange
語法:ZRANGE key start stop [WITHSCORES] 127.0.0.1:6379> zrange scoreboard 0 2 "zhangsan" "wangwu" "lisi「
從大到小的順序:zrevrange
語法:ZREVRANGE key start stop [WITHSCORES] 127.0.0.1:6379> zrevrange scoreboard 0 2 " lisi " "wangwu" " zhangsan 「
若是須要得到元素的分數的能夠在命令尾部加上WITHSCORES參數
127.0.0.1:6379> zrange scoreboard 0 1 WITHSCORES "zhangsan" "80" "wangwu" "94"
語法:ZCARD key 127.0.0.1:6379> ZCARD scoreboard (integer) 3
語法:ZCOUNT key min max 127.0.0.1:6379> ZCOUNT scoreboard 80 90 (integer) 1
從小到大 語法:ZRANK key member 127.0.0.1:6379> ZRANK scoreboard lisi (integer) 0 從大到小 語法:ZREVRANK key member 127.0.0.1:6379> ZREVRANK scoreboard zhangsan (integer) 1
語法:HEXISTS key field 判斷hash類型是否存在 某字段 127.0.0.1:6379> hexists user age 查看user中是否有age字段 (integer) 1 127.0.0.1:6379> hexists user name 查看user中是否有name字段 (integer) 0
EXPIRE key seconds 設置key的生存時間(單位:秒)key在多少秒後會自動刪除
TTL key 查看key生於的生存時間
PERSIST key 清除生存時間
PEXPIRE key milliseconds 生存時間設置單位爲:毫秒
例子: 192.168.101.3:7002> set test 1 設置test的值爲1 OK 192.168.101.3:7002> get test 獲取test的值 "1" 192.168.101.3:7002> EXPIRE test 5 設置test的生存時間爲5秒 (integer) 1 192.168.101.3:7002> TTL test 查看test的生於生成時間還有1秒刪除 (integer) 1 192.168.101.3:7002> TTL test (integer) -2 192.168.101.3:7002> get test 獲取test的值,已經刪除 (nil)
返回知足給定pattern 的全部key
redis 127.0.0.1:6379> keys mylist* "mylist" "mylist5" "mylist6" "mylist7" "mylist8"
返回 值的類型。這個方法能夠很是簡單的判斷出值的類型
redis 127.0.0.1:6379> type addr string redis 127.0.0.1:6379> type myzset2 zset redis 127.0.0.1:6379> type mylist list
RDB方式的持久化是經過快照(snapshotting)完成的,當符合必定條件時Redis會自動將內存中的數據進行快照並持久化到硬盤。RDB是Redis默認採用的持久化方式。
save 開頭的一行就是持久化配置,能夠配置多個條件(每行配置一個條件),每一個條件之間是「或」的關係。
「save 900 1」表示15分鐘(900秒鐘)內至少1個鍵被更改則進行快照。
「save 300 10」表示5分鐘(300秒)內至少10個鍵被更改則進行快照。
Redis啓動後會讀取RDB快照文件,將數據從硬盤載入到內存。根據數據量大小與結構和服務器性能不一樣,這個時間也不一樣。一般將記錄一千萬個字符串類型鍵、大小爲1GB的快照文件載入到內存中須要花費20~30秒鐘。
經過RDB方式實現持久化,一旦Redis異常退出,就會丟失最後一次快照之後更改的全部數據。這就須要開發者根據具體的應用場合,經過組合設置自動快照條件的方式來將可能發生的數據損失控制在可以接受的範圍。
若是數據很重要以致於沒法承受任何損失,則能夠考慮使用AOF方式進行持久化。
默認狀況下Redis沒有開啓AOF(append only file
)方式的持久化.
能夠經過修改redis.conf配置文件中的appendonly參數開啓
appendonly yes
開啓AOF持久化後每執行一條會更改Redis中的數據的命令
,Redis就會將該命令寫入硬盤中的AOF文件。
AOF文件的保存位置和RDB文件的位置相同,都是經過dir參數設置的。
dir ./
默認的文件名是appendonly.aof,能夠經過appendfilename參數修改:
appendfilename appendonly.aof
使用 AOF 持久化須要設置同步選項,從而確保寫命令同步到磁盤文件上的時機。這是由於對文件進行寫入並不會立刻將內容同步到磁盤上,而是先存儲到緩衝區,而後由操做系統決定何時同步到磁盤。有如下同步選項:
選項 | 同步頻率 |
---|---|
always | 每一個寫命令都同步 |
everysec | 每秒同步一次 |
no | 讓操做系統來決定什麼時候同步 |
隨着服務器寫請求的增多,AOF 文件會愈來愈大。Redis 提供了一種將 AOF 重寫的特性,可以去除 AOF 文件中的冗餘寫命令。
主Redis無需特殊配置;
從redis配置:修改 從redis服務器上的redis.conf文件。
slaveof 127.0.0.1 6379
: (slaveof ip port)
隨着負載不斷上升,主服務器可能沒法很快地更新全部從服務器,或者從新鏈接和從新同步從服務器將致使系統超載。爲了解決這個問題,能夠建立一個中間層
來分擔主服務器的複製工做。中間層的服務器是最上層服務器的從服務器,又是最下層服務器的主服務器。