redis是一個使用ANSI C編寫的開源、支持網絡、基于內存、可選持久性的鍵值對存儲數據庫——維基百科
可以簡單的說,Redis就是一款高性能的NoSQL數據庫
Redis學習筆記(后臺私信【Redis】免費領取)
01 什么是NoSQL?
我們前面所學習的MySQL數據庫是典型的的SQL數據庫也就是傳統的關系型數據庫,而我們今天學習的Redis數據庫則是一款NoSQL數據庫,也叫作非關系型數據庫,它與我們熟悉的MySQL等的概念完全是不一樣的,它是一項全新的數據庫理念,我們帖一組百度百科的解釋
NoSQL,泛指非關系型的數據庫。隨著互聯網web2.0網站的興起,傳統的關系數據庫在處理web2.0網站,特別是超大規模和高并發的SNS類型的web2.0純動態網站已經顯得力不從心,出現了很多難以克服的問題,而非關系型的數據庫則由于其本身的特點得到了非常迅速的發展。NoSQL數據庫的產生就是為了解決大規模數據集合多重數據種類帶來的挑戰,尤其是大數據應用難題——百度百科
說明:我們現在所看到的的博客,RSS,P2P,微博,抖音等均屬于 Web2.0的產物,Web2.0相比較過去的Web1.0更加注重于用戶的交互,用戶不僅可以瀏覽,還可以上傳一些資源到網站上,例如圖片文字或者說短視頻等,使得用戶也參與到了網站內容的制造中去了
02 為什么使用NoSQL?
- 部署成本低:部署操作簡單,以開源軟件為主
- 存儲格式豐富:支持 key-value形式、文檔、圖片等眾多形式,包括對象或者集合等格式
- 速度快:數據存儲在緩存中,而不是硬盤中,而且例如Redis基于鍵值對,同時不需要經過SQL層解析,性能非常高
- 無耦合性,易擴展
- 在SQL中,一個正在使用的數據是不允許刪除的,但NoSQL卻可以操作
03 NoSQL可以替代SQL嗎?
有人會說,NoSQL = Not SQL ,但是我更傾向這樣理解 NoSQL = Not only SQL ,我們不能以一個絕對的結論來判定兩項技術的好壞,每一項技術的產生都有其特定的原因,在我看來,NoSQL更適合作為SQL數據庫的補充,由于海量數據的出現,性能的要求高了起來,而NoSQL這種產物,對于結構簡單但是數據量大的數據處理起來要比傳統的SQL快很多,但是同樣的,其邏輯運算就必須很簡單,否則它也是力不從心的
在我看來,可以簡單的說,NoSQL就是以功能換取性能,但是需要處理復雜的業務邏輯還需要使用關系型數據庫,所以說想要在模型中完全用NoSQL替代SQL是不現實的,兩者更像是互補的關系
SQL的好處:
- 支持在一個表以及多表之前進行復雜的查詢操作
- 支持對事物的處理,能保證數據的安全要求
- 學習成本低,資料較多
市面上的NoSQL產品非常多,我們今天所要介紹的就是其中一款基于鍵值存儲的數據庫——Redis
04 初識Redis
我們在一開始提到了,Redis就是一款高性能的NoSQL數據庫,那么它的應用場景是什么呢?
Redis學習思維導圖(xmind)后臺私信【Redis】免費領取
- 用于用戶內容緩存,可以處理大量數據的高訪問負載,例如:數據查詢,新聞,商品內容
- 任務隊列,例如:秒殺,12306
- 在線好友列表
- 應用、網站訪問統計排行
由于其基于鍵值存儲,那么可以支持的存儲的類型有什么呢?
- 字符串類型 - String
- 列表 - list:linkedlist
- 集合 - set
- 有序集合 - sortedset
- 哈希 - hash:map
05 下載安裝
5.1 linux
官網:redis.io
由于官網訪問速度過慢,我們可以訪問對應的中文網:www.redis.net.cn
下載,解壓,編譯:
$ wget http://download.redis.io/releases/redis-5.0.4.tar.gz $ tar xzf redis-5.0.4.tar.gz $ cd redis-5.0.4 $ make
二進制文件是編譯完成后在src目錄下. 運行如下:
$ src/redis-server
你能使用Redis的內置客戶端進行進行redis代碼的編寫,例如我們存入一個鍵值 name-zhangsan
$ src/redis-cli redis> set name zhangsan OK redis> get name "zhangsan"
5.2 windows
我們可以去github中尋找windows版本,不過版本會有所滯后
github.com/microsoftar…
解壓即可用
- redis-server.exe:redis服務器端
- redis-cli.exe:redis的客戶端
- redis.windows.conf:配置文件
06 常見支持類型—存取刪除命令操作
6.1 字符串類型 - String
(1) 存儲
- set key value
- 127.0.0.1:6379> set address beijing - OK
(2) 獲取
- get key
- 127.0.0.1:6379> get address - “beijing”
(3) 刪除
- del key
- 127.0.0.1:6379> del address - (integer) 1
6.2 列表類型 - list
添加一個元素到列表的頭部(左邊)或者尾部(右邊)
(1) 添加
- lpush key value:將元素添加到列表左邊
- Rpush key value:將元素添加到列表右邊
127.0.0.1:6379> lpush listDemo zhangsan (integer) 1 127.0.0.1:6379> lpush listDemo lisi (integer) 2 127.0.0.1:6379> rpush listDemo wangwu (integer) 3
(2) 獲取:lrange key start end
- 127.0.0.1:6379> lrange listDemo 0 -1
1) "lisi" 2) "zhangsan" 3) "wangwu"
(3) 刪除
- lpop key:刪除列表最左邊的元素,且返回元素
- rpop key:刪除列表最右邊的元素,且返回元素
6.3 集合類型 - set
set:String 類型的無序集合,且元素不能重復
(1) 存儲
- sadd key value
127.0.0.1:6379> sadd setDemo aaa (integer) 1 127.0.0.1:6379> sadd setDemo aaa (integer) 0
(2) 獲取
- smembers key:獲取set集合中的所有元素
127.0.0.1:6379> smembers setDemo 1) "aaa“
(3) 刪除
- srem key value:刪除set集合中某元素
127.0.0.1:6379> srem setDemo aaa (integer) 1
6.4 有序集合類型 - sortedset
sortedset 和 set 一樣也是 string 類型元素的集合,且不允許重復的元素
不同的是每個元素都會關聯一個double類型的分數,redis正是通過分數來為集合中的成員進行從小到大的排序
有序集合的成員是唯一,但分數(score)卻可以重復
(1) 存儲
- zadd key score value
127.0.0.1:6379> zadd sortedsetDemo 20 zhangsan (integer) 1 127.0.0.1:6379> zadd sortedsetDemo 10 lisi (integer) 1 127.0.0.1:6379> zadd sortedsetDemo 60 wangwu (integer) 1
(2) 獲取
- zrange key start end [withscores]
127.0.0.1:6379> zrange sortedsetDemo 0 -1 1) "lisi" 2) "zhangsan" 3) "wangwu"
(3) 刪除
- zrem key value
127.0.0.1:6379> zrem sortedsetDemo wangwu (integer) 1
6.5 哈希類型 - hash
(1) 存儲
- hset key field value
127.0.0.1:6379> hset hashDemo username admin (integer) 1 127.0.0.1:6379> hset hashDemo password admin (integer) 1
(2) 獲取
- hget key field:獲取指定的field對應的值
127.0.0.1:6379> hget hashDemo password "admin"
- hgetall key:獲取所有的field和value
127.0.0.1:6379> hgetall hashDemo
1) "username"
2) "admin"
3) "password"
4) "admin"
(3) 刪除
- hdel key field
127.0.0.1:6379> hdel hashDemo username (integer) 1
07 數據持久化
開篇已經講過,Redis是一個內存數據庫,也就是說,我們的數據全部存儲在內存中,而我們常見的MySQL和Oracle等SQL數據庫會將數據存儲到硬盤中,凡事都是有利有弊,雖然內存數據庫讀寫速度要比在硬盤中讀寫的數據庫快的多,但是卻出現了一個很麻煩的問題,也就是說,當 Redis 服務器重啟或者宕機后,內存中的數據會全部丟失,為了解決這個問題,Redis提供了一種持久化的技術,也就是將內存中的數據存儲到硬盤中去,日后方便我們使用這些文件恢復數據庫中的數據
7.1 RDB 方式 (默認方式)
RDB:一定的時間內,檢測key的變化情況,然后持久化數據
我們想要配置它,需要編輯 redis.windows.conf 配置文件
# Save the DB on disk: # # save <seconds> <changes> # # Will save the DB if both the given number of seconds and the given # number of write operations against the DB occurred. # # In the example below the behaviour will be to save: # after 900 sec (15 min) if at least 1 key changed # after 300 sec (5 min) if at least 10 keys changed # after 60 sec if at least 10000 keys changed # ......省略部分 save 900 1 save 300 10 save 60 10000
我們需要修改的就是最后三行,前面的說明的意思是,如果給定的秒數和給定的對數據庫的寫操作數同時發生,那么將保存數據庫,也就是說,它的配置是根據save后面的兩個數字,根據說明可知,第一個數字代表間隔時間,第二個數代表操作數據的數量
例如第一個 save 900 1 ,就是說每900秒且,至少一個 key 被改變則保存數據
我們根據自己具體項目的需要設置好后,需要重新啟動Redis的服務器,并且我們需要指定配置文件,我們先指向到Redis指定目錄下, 然后輸入命令 redis-server.exe redis.windows.conf
例如我本地:D:ToolsRedis-x64-3.2.100>redis-server.exe redis.windows.conf
7.2 AOF 方式
AOF:每一次操作后,就持久化數據
我們同樣可以在 redis.windows.conf 文件配置
我們找到這一行
Appendonly no no代表關閉aof,改為yes代表開啟
還有這一行
# appendfsync no:不進行持久化
我們可以修改 no 位置的值
- appendfsync always:每一次操作都進行持久化
- appendfsync everysec:每隔一秒進行一次持久化
08 Jedis - JAVA中操作Redis數據庫
Jedis is a blazingly small and sane Redis java client.
Jedis was conceived to be EASY to use.
Jedis 是一款可以讓我們在java中操作redis數據庫的工具,下載其jar包導入即可,使用還是非常簡單的
8.1 字符串類型 - String
//獲取連接,空構造代表默認值 "localhost",6379端口 Jedis jedis = new Jedis(); //存儲 jedis.set("address","beijing"); //獲取 String address = jedis.get("address"); //關閉連接 jedis.close();
補充:setex() 方法可以存儲數據,并且指定過期時間
//將aaa-bbb存入,且10秒后過期 jedis.setex("aaa",10,"bbb")
8.2 列表類型 - list
//獲取連接,空構造代表默認值 "localhost",6379端口 Jedis jedis = new Jedis(); //存儲 jedis.lpush("listDemo","zhangsan","lisi","wangwu");//從左 jedis.rpush("listDemo","zhangsan","lisi","wangwu");//從右 //獲取 List<String> mylist = jedis.lrange("listDemo", 0, -1); //刪除,并且返回元素 String e1 = jedis.lpop("listDemo");//從左 String e2 = jedis.rpop("listDemo");//從右 //關閉連接 jedis.close();
8.3 集合類型 - set
//獲取連接,空構造代表默認值 "localhost",6379端口 Jedis jedis = new Jedis(); //存儲 jedis.sadd("setDemo","zhangsan","lisi","wangwu"); //獲取 Set<String> setDemo = jedis.smembers("setDemo"); //關閉連接 jedis.close();
8.4 有序集合類型 - sortedset
//獲取連接,空構造代表默認值 "localhost",6379端口 Jedis jedis = new Jedis(); //存儲 jedis.zadd("sortedsetDemo",20,"zhangsan"); jedis.zadd("sortedsetDemo",10,"lisi"); jedis.zadd("sortedsetDemo",60,"wangwu"); //獲取 Set<String> sortedsetDemo = jedis.zrange("sortedsetDemo", 0, -1); //關閉連接 jedis.close();
8.5 哈希類型 - hash
//獲取連接,空構造代表默認值 "localhost",6379端口 Jedis jedis = new Jedis(); //存儲 jedis.hset("hashDemo","name","lisi"); jedis.hset("hashDemor","age","20"); //獲取 String name = jedis.hget("hashDemo", "name"); //獲取所有數據 Map<String, String> user = jedis.hgetAll("hashDemo"); Set<String> keySet = user.keySet(); for (String key : keySet) { //獲取value String value = user.get(key); System.out.println(key + ":" + value); } //關閉連接 jedis.close();
09 Jedis 連接池
為什么我們要使用連接池呢?
我們要使用Jedis,必須建立連接,我們每一次進行數據交互的時候,都需要建立連接,Jedis雖然具有較高的性能,但建立連接卻需要花費較多的時間,如果使用連接池則可以同時在客戶端建立多個連接并且不釋放,連接的時候只需要通過一定的方式獲取已經建立的連接,用完則歸還到連接池,這樣時間就大大的節省了
//創建一個配置對象 JedisPoolConfig config = new JedisPoolConfig(); config.setMaxIdle(10); //創建Jedis連接池對象 JedisPool jedisPool = new JedisPool(config,"localhost",6379); //獲取連接 Jedis jedis = jedisPool.getResource(); //使用 jedis.set("setDemo","zhangsan"); //關閉 歸還到連接池中 jedis.close();
10 連接池工具類
public class JedisPoolUtils { private static JedisPool jedisPool; //靜態代碼初始化池配置 static{ //創建Properties對象 Properties pro = new Properties(); //讀取配置文件 InputStream is = JedisPoolUtils.class.getClassLoader().getResourceAsStream("jedis.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(); } }
如果文章中有什么不足,或者錯誤的地方,歡迎大家留言分享想法,感謝朋友們的支持!
原文鏈接:https://juejin.im/post/5d96a98fe51d4578080330c1