redis是一款高性能的NOSQL系列的非關係型數據庫php
1.1.什麼是NOSQL
NoSQL(NoSQL = Not Only SQL),意即「不只僅是SQL」,是一項全新的數據庫理念,泛指非關係型的數據庫。
隨着互聯網web2.0網站的興起,傳統的關係數據庫在應付web2.0網站,特別是超大規模和高併發的SNS類型的web2.0純動態網站已經顯得力不從心,暴露了不少難以克服的問題,而非關係型的數據庫則因爲其自己的特色獲得了很是迅速的發展。NoSQL數據庫的產生就是爲了解決大規模數據集合多重數據種類帶來的挑戰,尤爲是大數據應用難題。html
1.1.1. NOSQL和關係型數據庫比較
優勢:
1)成本:nosql數據庫簡單易部署,基本都是開源軟件,不須要像使用oracle那樣花費大量成本購買使用,相比關係型數據庫價格便宜。
2)查詢速度:nosql數據庫將數據存儲於緩存之中,關係型數據庫將數據存儲在硬盤中,天然查詢速度遠不及nosql數據庫。
3)存儲數據的格式:nosql的存儲格式是key,value形式、文檔形式、圖片形式等等,因此能夠存儲基礎類型以及對象或者是集合等各類格式,而數據庫則只支持基礎類型。
4)擴展性:關係型數據庫有相似join這樣的多表查詢機制的限制致使擴展很艱難。java
缺點:
1)維護的工具和資料有限,由於nosql是屬於新的技術,不能和關係型數據庫10幾年的技術同日而語。
2)不提供對sql的支持,若是不支持sql這樣的工業標準,將產生必定用戶的學習和使用成本。
3)不提供關係型數據庫對事務的處理。c++
1.1.2. 非關係型數據庫的優點:
1)性能NOSQL是基於鍵值對的,能夠想象成表中的主鍵和值的對應關係,並且不須要通過SQL層的解析,因此性能很是高。
2)可擴展性一樣也是由於基於鍵值對,數據之間沒有耦合性,因此很是容易水平擴展。git
1.1.3. 關係型數據庫的優點:
1)複雜查詢能夠用SQL語句方便的在一個表以及多個表之間作很是複雜的數據查詢。
2)事務支持使得對於安全性能很高的數據訪問要求得以實現。對於這兩類數據庫,對方的優點就是本身的弱勢,反之亦然。github
1.1.4. 總結
關係型數據庫與NoSQL數據庫並不是對立而是互補的關係,即一般狀況下使用關係型數據庫,在適合使用NoSQL的時候使用NoSQL數據庫,
讓NoSQL數據庫對關係型數據庫的不足進行彌補。
通常會將數據存儲在關係型數據庫中,在nosql數據庫中備份存儲關係型數據庫的數據web
1.2.主流的NOSQL產品
• 鍵值(Key-Value)存儲數據庫
相關產品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
典型應用: 內容緩存,主要用於處理大量數據的高訪問負載。
數據模型: 一系列鍵值對
優點: 快速查詢
劣勢: 存儲的數據缺乏結構化
• 列存儲數據庫
相關產品:Cassandra, HBase, Riak
典型應用:分佈式的文件系統
數據模型:以列簇式存儲,將同一列數據存在一塊兒
優點:查找速度快,可擴展性強,更容易進行分佈式擴展
劣勢:功能相對侷限
• 文檔型數據庫
相關產品:CouchDB、MongoDB
典型應用:Web應用(與Key-Value相似,Value是結構化的)
數據模型: 一系列鍵值對
優點:數據結構要求不嚴格
劣勢: 查詢性能不高,並且缺少統一的查詢語法
• 圖形(Graph)數據庫
相關數據庫:Neo4J、InfoGrid、Infinite Graph
典型應用:社交網絡
數據模型:圖結構
優點:利用圖結構相關算法。
劣勢:須要對整個圖作計算才能得出結果,不容易作分佈式的集羣方案。
1.3 什麼是Redis
Redis是用C語言開發的一個開源的高性能鍵值對(key-value)數據庫,官方提供測試數據,50個併發執行100000個請求,讀的速度是110000次/s,寫的速度是81000次/s ,且Redis經過提供多種鍵值數據類型來適應不一樣場景下的存儲需求,目前爲止Redis支持的鍵值數據類型以下:
1) 字符串類型 string
2) 哈希類型 hash
3) 列表類型 list
4) 集合類型 set
5) 有序集合類型 sortedset
1.3.1 redis的應用場景
• 緩存(數據查詢、短鏈接、新聞內容、商品內容等等)
• 聊天室的在線好友列表
• 任務隊列。(秒殺、搶購、12306等等)
• 應用排行榜
• 網站訪問統計
• 數據過時處理(能夠精確到毫秒
• 分佈式集羣架構中的session分離ajax
1. 官網:https://redis.io
2. 中文網:http://www.redis.net.cn/redis
Win版 :https://github.com/MicrosoftArchive/redis
3. 解壓直接可使用:
* redis.windows.conf:配置文件算法
Redis的經常使用基本配置 | ||
配置項 | 示例 | 說明 |
daemonize | daemonize yes | 是否啓用後臺運行,默認no |
port | port 6379 | 設置端口號,默認6379 |
logfile | logfile 日誌文件 | 設置日誌文件 |
databases | databases 255 | 設置redis數據庫總量 |
dir | dir 數據文件目錄 | 設置數據文件存儲目錄 |
requirepass | requirepass 12345 | 設置使用密碼 |
* redis-cli.exe:redis的客戶端
* redis-server.exe:redis服務器端
* redis存儲的是:key,value格式的數據,其中key都是字符串,value有5種不一樣的數據結構
* value的數據結構:
1) 字符串類型 string
2) 哈希類型 hash : map格式
3) 列表類型 list : linkedlist格式。支持重複元素
4) 集合類型 set : 不容許重複元素
5) 有序集合類型 sortedset:不容許重複元素,且元素有順序
1. 存儲: set key value
127.0.0.1:6379> set username zhangsan
OK
2. 獲取: get key
127.0.0.1:6379> get username
"zhangsan"
3. 刪除: del key
127.0.0.1:6379> del age
(integer) 1
1. 存儲: hset key field value
127.0.0.1:6379> hset myhash username lisi
(integer) 1
127.0.0.1:6379> hset myhash password 123
(integer) 1
2. 獲取:
* hget key field: 獲取指定的field對應的值
127.0.0.1:6379> hget myhash username
"lisi"
* hgetall key:獲取全部的field和value
127.0.0.1:6379> hgetall myhash
1) "username"
2) "lisi"
3) "password"
4) "123"
3. 刪除: hdel key field
127.0.0.1:6379> hdel myhash username
(integer) 1
list:能夠添加一個元素到列表的頭部(左邊)或者尾部(右邊)
1. 添加:
1. lpush key value: 將元素加入列表左表
2. rpush key value:將元素加入列表右邊
127.0.0.1:6379> lpush myList a
(integer) 1
127.0.0.1:6379> lpush myList b
(integer) 2
127.0.0.1:6379> rpush myList c
(integer) 3
2. 獲取:
* lrange key start end :範圍獲取
127.0.0.1:6379> lrange myList 0 -1
1) "b"
2) "a"
3) "c"
3. 刪除:
* lpop key: 刪除列表最左邊的元素,並將元素返回
* rpop key: 刪除列表最右邊的元素,並將元素返回
1. 存儲:sadd key value
127.0.0.1:6379> sadd myset a
(integer) 1
127.0.0.1:6379> sadd myset a
(integer) 0
2. 獲取:smembers key:獲取set集合中全部元素
127.0.0.1:6379> smembers myset
1) "a"
3. 刪除:srem key value:刪除set集合中的某個元素
127.0.0.1:6379> srem myset a
(integer) 1
不容許重複元素,且元素有順序.每一個元素都會關聯一個double類型的分數。redis正是經過分數來爲集合中的成員進行從小到大的排序。
1. 存儲:zadd key score value
127.0.0.1:6379> zadd mysort 60 zhangsan
(integer) 1
127.0.0.1:6379> zadd mysort 50 lisi
(integer) 1
127.0.0.1:6379> zadd mysort 80 wangwu
(integer) 1
2. 獲取:zrange key start end [withscores]
127.0.0.1:6379> zrange mysort 0 -1
1) "lisi"
2) "zhangsan"
3) "wangwu"
127.0.0.1:6379> zrange mysort 0 -1 withscores
1) "zhangsan"
2) "60"
3) "wangwu"
4) "80"
5) "lisi"
6) "500"
3. 刪除:zrem key value
127.0.0.1:6379> zrem mysort lisi
(integer) 1
1. keys * : 查詢全部的鍵
2. type key : 獲取鍵對應的value的類型
3. del key:刪除指定的key value
1. redis是一個內存數據庫,當redis服務器重啓,獲取電腦重啓,數據會丟失,咱們能夠將redis內存中的數據持久化保存到硬盤的文件中。
2. redis持久化機制:
1. RDB:默認方式,不須要進行配置,默認就使用這種機制
* 在必定的間隔時間中,檢測key的變化狀況,而後持久化數據
1. 編輯redis.windwos.conf文件
# after 900 sec (15 min) if at least 1 key changed
save 900 1
# after 300 sec (5 min) if at least 10 keys changed
save 300 10
# after 60 sec if at least 10000 keys changed
save 60 10000
2. 從新啓動redis服務器,並指定配置文件名稱
D:\JavaWeb2018\day23_redis\資料\redis\windows-64\redis-2.8.9>redis-server.exe redis.windows.conf
2. AOF:日誌記錄的方式,能夠記錄每一條命令的操做。能夠每一次命令操做後,持久化數據
1. 編輯redis.windwos.conf文件
appendonly no(關閉aof) --> appendonly yes (開啓aof)
# appendfsync always : 每一次操做都進行持久化
appendfsync everysec : 每隔一秒進行一次持久化
# appendfsync no : 不進行持久化
* Jedis: 一款java操做redis數據庫的工具.
* 使用步驟:
1. 下載jedis的jar包
2. 使用
//1. 獲取鏈接 Jedis jedis = new Jedis("localhost",6379); //2. 操做 jedis.set("username","zhangsan"); //3. 關閉鏈接 jedis.close();
* Jedis操做各類redis中的數據結構
set
get
//1. 獲取鏈接 Jedis jedis = new Jedis();//若是使用空參構造,默認值 "localhost",6379端口 //2. 操做 //存儲 jedis.set("username","zhangsan"); //獲取 String username = jedis.get("username"); System.out.println(username); //可使用setex()方法存儲能夠指定過時時間的 key value jedis.setex("activecode",20,"hehe");//將activecode:hehe鍵值對存入redis,而且20秒後自動刪除該鍵值對 //3. 關閉鏈接 jedis.close();
hset
hget
hgetAll
//1. 獲取鏈接 Jedis jedis = new Jedis();//若是使用空參構造,默認值 "localhost",6379端口 //2. 操做 // 存儲hash jedis.hset("user","name","lisi"); jedis.hset("user","age","23"); jedis.hset("user","gender","female"); // 獲取hash String name = jedis.hget("user", "name"); System.out.println(name); // 獲取hash的全部map中的數據 Map<String, String> user = jedis.hgetAll("user"); // keyset Set<String> keySet = user.keySet(); for (String key : keySet) { //獲取value String value = user.get(key); System.out.println(key + ":" + value); } //3. 關閉鏈接 jedis.close();
lpush / rpush
lpop / rpop
lrange start end : 範圍獲取
//1. 獲取鏈接 Jedis jedis = new Jedis();//若是使用空參構造,默認值 "localhost",6379端口 //2. 操做 // list 存儲 jedis.lpush("mylist","a","b","c");//從左邊存 jedis.rpush("mylist","a","b","c");//從右邊存 // list 範圍獲取 List<String> mylist = jedis.lrange("mylist", 0, -1); System.out.println(mylist); // list 彈出 String element1 = jedis.lpop("mylist");//c System.out.println(element1); String element2 = jedis.rpop("mylist");//c System.out.println(element2); // list 範圍獲取 List<String> mylist2 = jedis.lrange("mylist", 0, -1); System.out.println(mylist2); //3. 關閉鏈接 jedis.close();
sadd
smembers:獲取全部元素
//1. 獲取鏈接 Jedis jedis = new Jedis();//若是使用空參構造,默認值 "localhost",6379端口 //2. 操做 // set 存儲 jedis.sadd("myset","java","php","c++"); // set 獲取 Set<String> myset = jedis.smembers("myset"); System.out.println(myset); //3. 關閉鏈接 jedis.close();
zadd
zrange
//1. 獲取鏈接 Jedis jedis = new Jedis();//若是使用空參構造,默認值 "localhost",6379端口 //2. 操做 // sortedset 存儲 jedis.zadd("mysortedset",3,"亞瑟"); jedis.zadd("mysortedset",30,"後裔"); jedis.zadd("mysortedset",55,"孫悟空"); // sortedset 獲取 Set<String> mysortedset = jedis.zrange("mysortedset", 0, -1); System.out.println(mysortedset); //3. 關閉鏈接 jedis.close();
* 使用:
1. 建立JedisPool鏈接池對象
2. 調用方法 getResource()方法獲取Jedis鏈接
//0.建立一個配置對象 JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(50); config.setMaxIdle(10); //1.建立Jedis鏈接池對象 JedisPool jedisPool = new JedisPool(config,"localhost",6379); //2.獲取鏈接 Jedis jedis = jedisPool.getResource(); //3. 使用 jedis.set("hehe","heihei"); //4. 關閉 歸還到鏈接池中 jedis.close();
jedis詳細配置.properties
#最大活動對象數 redis.pool.maxTotal=1000 #最大可以保持idel狀態的對象數 redis.pool.maxIdle=100 #最小可以保持idel狀態的對象數 redis.pool.minIdle=50 #當池內沒有返回對象時,最大等待時間 redis.pool.maxWaitMillis=10000 #當調用borrow Object方法時,是否進行有效性檢查 redis.pool.testOnBorrow=true #當調用return Object方法時,是否進行有效性檢查 redis.pool.testOnReturn=true #「空閒連接」檢測線程,檢測的週期,毫秒數。若是爲負值,表示不運行「檢測線程」。默認爲-1. redis.pool.timeBetweenEvictionRunsMillis=30000 #向調用者輸出「連接」對象時,是否檢測它的空閒超時; redis.pool.testWhileIdle=true # 對於「空閒連接」檢測線程而言,每次檢測的連接資源的個數。默認爲3. redis.pool.numTestsPerEvictionRun=50 #redis服務器的IP redis.ip=xxxxxx #redis服務器的Port redis1.port=6379
* 鏈接池工具類
public class JedisPoolUtils { private static JedisPool jedisPool; static{ //讀取配置文件 InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.properties"); //建立Properties對象 Properties pro = new Properties(); //關聯文件 try { pro.load(is); } catch (IOException e) { e.printStackTrace(); } //獲取數據,設置到JedisPoolConfig中 JedisPoolConfig config = new JedisPoolConfig(); config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal"))); config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle"))); //初始化JedisPool jedisPool = new JedisPool(config,pro.getProperty("host"),Integer.parseInt(pro.getProperty("port"))); } /** * 獲取鏈接方法 */ public static Jedis getJedis(){ return jedisPool.getResource(); } }
## 案例:
案例需求:
1. 提供index.html頁面,頁面中有一個省份 下拉列表
2. 當 頁面加載完成後 發送ajax請求,加載全部省份
* 注意:使用redis緩存一些不常常發生變化的數據。 * 數據庫的數據一旦發生改變,則須要更新緩存。 * 數據庫的表執行 增刪改的相關操做,須要將redis緩存數據狀況,再次存入 * 在service對應的增刪改方法中,將redis數據刪除。