1 nosql的概念
sql:操作(關系型)數據庫的標准查詢語言
關系型數據庫(rdbms):以關系(由行和列組成的二維表)模型為核心數據庫,有表的儲存系統。(mysql、oracle、sqlserver...)
nosql:針對非關系型數據庫的語言,彌補關系型數據庫的一些缺點,主要用到大的數據量或者高並發的場景下。
非關系型數據庫分類:
2 Redis
2.1 Redis是什么
(1) Redis 是一個高性能的 開源的、C語言寫的Nosql(非關系型數據庫),數據保存可以存儲在內存中或者磁盤中。
(2) Redis 是以key-value形式存儲,和傳統的關系型數據庫不一樣。不一定遵循傳統數據庫的一些基本要求,
比如說,不遵循sql標准,事務,表結構等等,redis嚴格上不是一種數據庫,應該是一種數據結構化存儲方
法的集合。(數據結構:數組,list,set,map等)
redis提供了一下操作方法,我們使用這些方法就可以對存入字符串,組織成各種類型數據庫結構
(string,list,set,map等)
小結:
(1) redis開源 高性能nosql數據庫,數據可以存儲在內存或磁盤上面
(2) Redis 主要key-value結構形式存儲,redis底層支持各種類型的數據存儲結構
包括 list set map string等。
2.2 特點(優勢)
1. 數據保存在內存,存取速度快,並發能力強。
2. 它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、 zset(sorted set --有序集合)
和hash(哈希類型)。
3. redis的出現,很大程度補償了memcached這類key/value存儲的不足,在部分場合可以對關系數據庫(如MySQL)起到很好的補充作用。
4. 它提供了Java,C/C++,C#,PHP,JavaScript等客戶端,使用很方便。
5. Redis支持集群(主從同步)。數據可以主服務器向任意數量從的從服務器上同步,從服務器可以是關聯其他從服務器的主服務器。
6. 支持持久化,可以將數據保存在硬盤的文件中。
7. 支持訂閱/發布(subscribe/publish)功能 QQ群
總結:
1. 數據存儲:存放在內存,還支持持久化.-存取速度快,並發能力強,數據安全性高
2. 支持value類
3. 支持多個語言客戶端
4. 還支持集群(支持高並發,海量數據)
2.3 Redis的使用場景
(1) 最多,就是緩存(cache 使用空間換取時間) --redis
(2) 計數器應用 -- 微博 熱點新聞 -- 轉載 點贊(高並發)
(3) 實時防攻擊系統 -- 銀行網站 (登錄) --計數 (ip 同一個ip + 5)
redis--支持斷電恢復 內存和磁盤
(4) 有效期的應用 -- 道具 紅包 優惠券 ...
(5) 支持無序的場景 -- set特效
(6) 隊列 -->quene -->秒殺 搶購 --redis
(7) 消息系統訂閱發布 -->redis(MQ消息隊列--高並發 秒殺 搶購 轉發 )
2.4 Mysql、Memcached和Redis的區別
|
mysql |
redis |
memcached |
類型 |
關系型 |
非關系型 |
非關系型 |
存儲位置 |
磁盤 |
磁盤和內存 |
內存 |
存儲過期 |
不支持 |
支持 |
支持 |
讀寫性能 |
低 |
非常高 |
非常高 |
3 使用redis-cli客戶端操作Redis
3.1 對字符串操作
對value為string類型的常用操作:
set key value //將字符串值value關聯到key
get key //返回key關聯的字符串值
mset //同時設置一個或多個key-value對
mget //返回所有(一個或多個)給定key的值
incr key //將 key 中儲存的數字值增1(key不存在,則初始化為0,再加1)
decr key //將 key 中儲存的數字值減1(key不存在,則初始化為0,再減1)
incrBy key //自增多少
decrBy key //自減多少
3.2 對key的常用操作
keys * //獲取所有key列表
del key //刪除key
expire key xx //設置key的過期時間(xx秒后過期)
ttl key //查看key的過期時間
flushall //清空整個redis服務器數據,所有的數據庫全部清空
flushdb //清除當前庫,redis中默認有16個數據庫,名稱分別為0,1,2.。。15
select index --select 0
3.3 對list集合的常用操作
list集合可以看成是一個左右排列的隊列(列表)
lpush key value //將一個或多個值 value 插入到列表 key 的表頭(最左邊)
rpush key value //將一個或多個值 value 插入到列表 key 的表尾(最右邊)
lpop key //移除並返回列表 key 的頭(最左邊)元素。
rpop key //移除並返回列表 key 的尾(最右邊)元素。
lrange key start stop//返回列表 key 中指定區間內的元素,查詢所有的stop為-1即可
lrem key count value//根據count值移除列表key中與參數 value 相等的元素count > 0 : 從表頭開始向表尾搜索,移除與 value 相等的元素,數量為 count 。count < 0 : 從表尾開始向表頭搜索,移除與 value 相等的元素,數量為 count 的絕對值。count = 0 : 移除表中所有與 value 相等的值。
lindex key index //返回列表 key 中,下標為 index 的元素
ltrim key start stop //對一個列表進行修剪
存放都是字符串,由redis組織成各種數據結構,Redis怎么實現棧(FILO)和隊列(FIFO)?
list控制同一邊進,同一邊出就是棧
list控制一邊進,另一邊出就是隊列
3.4 對set集合的常用操作
set集合是一個無序的不含重復值的隊列
sadd key member //將一個或多個 member 元素加入到集合 key 當中,已經存在於集合的 member 元素將被忽略
srem key member//移除集合 key 中的一個或多個 member 元素,不存在的 member 元素會被忽略
smembers key //返回集合 key 中的所有成員。
3.5 對hash類型的常用操作
hash類型類似於php的數組
hset key name value//添加一個name=>value鍵值對到key這個hash類型
hget key name //獲取hash類型的name鍵對應的值
hmset key name1 key1 name2 key2 //批量添加name=>value鍵值對到key這個hash類型
hmget key name1 name2//批量獲取hash類型的鍵對應的值
hkeys //返回哈希表 key 中的所有鍵
hvals //返回哈希表 key 中的所有值
hgetall //返回哈希表 key 中,所有的鍵和值
3.6 事務(弱事務,很少用)
multi //標記一個事務塊的開始。
exec //執行所有事務塊內的命令。
弱事務 : 日志
強事務 :同時成功 同時失敗-- 金融數據
discard //取消事務,放棄執行事務塊內的所有命令。
Redis的事務在執行exec指令時,才批量執行操作,沒有回滾操作
3.7 設置密碼
(1)通過命令動態調整密碼
CONFIG SET 命令可以動態地調整 Redis 服務器的配置而無須重啟,重啟后失效
CONFIG SET requirepass 123456 //將密碼設置為123456
CONFIG SET requirepass "" //清除密碼
AUTH 123456 //輸入密碼進行認證
(2)通過配置文件設置密碼
在配置文件redis.widows.conf中增加一行代碼
requirepass 123456
將密碼123456設置到配置文件中,redis啟動時加載該文件,即可啟用密碼
4 通過java操作Redis
4.1 選擇java客戶端
原來mysql需要使用jdbc,現在需要redis的一個java客戶端jedis。
jedis是客戶端,而reids是服務器。使用jedis這個java客戶端操作redis數據庫。
4.2 jedis簡單操作
4.2.1 簡單配置
使用jedis客戶端,完成jedis簡單操作
@Test public void test()throws Exception{ //創建連接 String host ="127.0.0.1"; int port = 6379; int timeout = 1000;//超時時間,1秒超時 Jedis jedis = new Jedis(host,port,timeout); jedis.auth("admin"); //執行操作 jedis.set("yhptest","yhptest dbl!"); System.out.println(jedis.get("yhptest")); //關閉連接 jedis.close(); }
4.2.2 配置連接池
通過jedis連接池,簡單操作redis數據庫
// 思想:如果創建一個對象后需要為他設置很多值,還不如先創建它配置對象並做完配置,然后再通過配置對象創建它 //1 創建jedispool配置對象 //2 做配置-四個 //3 創建jedispool //4 通過jedispool獲取連接 //5 執行操作 // 6 釋放連接 // 7 摧毀連接池-如果是真正項目中它應該是一個受spring管理的單例 @Test public void test()throws Exception{ //1 創建jedispool配置對象 JedisPoolConfig config = new JedisPoolConfig(); //2 做配置-四個 config.setMaxIdle(2); config.setMaxTotal(10); config.setMaxWaitMillis(1*1000); //創建連接超時 config.setTestOnBorrow(true);//獲取連接是測試連接是否暢通 //3 創建jedispool //1*1000 獲取連接超時時間 JedisPool pool = new JedisPool(config, "127.0.0.1",6379,1*1000,"admin"); //4 通過jedispool獲取連接 Jedis jedis = pool.getResource(); //5 執行操作 jedis.set("jedispooltest","dbldblddzt....."); System.out.println(jedis.get("jedispooltest")); // 6 釋放連接 jedis.close(); //底層做了兼容,如果是連接池操作就是釋放,如果是連接操作就是關閉 // 7 摧毀連接池-如果是真正項目中它應該是一個受spring管理的單例 pool.destroy(); }
4.3 jedis數據結構操作
@Test public void testRedis() throws Exception { Jedis jedis = new Jedis("127.0.0.1", 6379, 1000 * 10); jedis.auth("123456"); jedis.set("name", "龍傲天"); System.out.println(jedis.get("name")); jedis.close(); } @Test public void testRedisPool() throws Exception { //連接池 JedisPoolConfig config = new JedisPoolConfig(); config.setMaxIdle(2); config.setMaxTotal(10); JedisPool jedisPool = new JedisPool(config, "127.0.0.1", 6379, 1000 * 10, "123456"); Jedis jedis = jedisPool.getResource(); jedis.flushDB(); //字符串操作 jedis.set("name", "趙日天"); jedis.set("age", "18"); System.out.println(jedis.get("name")); System.out.println(jedis.get("age")); System.out.println(jedis.keys("*")); System.out.println("========================================"); //list集合操作 jedis.lpush("students","五五開","蕪湖神","王慕霸","古手羽","蕪湖神"); System.out.println(jedis.lrange("students", 0, -1)); jedis.lrem("students", 1, "蕪湖神"); System.out.println(jedis.lrange("students", 0, -1)); System.out.println("========================================"); //set集合操作 jedis.sadd("users","古天樂","劉德華","梁朝偉","黎明","張學友","劉德華"); System.out.println(jedis.smembers("users")); jedis.srem("users","張學友"); System.out.println(jedis.smembers("users")); System.out.println("========================================"); //hash操作 jedis.hset("players", "name","James"); System.out.println(jedis.hget("players", "name")); System.out.println("========================================"); //排序 jedis.lpush("nums","3","6","2","9","1"); System.out.println(jedis.lrange("nums", 0, -1)); System.out.println(jedis.sort("nums",new SortingParams().desc())); jedis.lpush("language","php","c++","java","h5","test","ui"); System.out.println(jedis.lrange("language", 0, -1)); SortingParams sortingParams = new SortingParams().desc().alpha(); System.out.println(jedis.sort("language", sortingParams)); jedis.flushDB(); jedis.close(); jedisPool.destroy(); }
事務操作
@Test public void testTransaction() throws Exception { JedisPoolConfig config = new JedisPoolConfig(); config.setMaxIdle(2); config.setMaxTotal(10); JedisPool jedisPool = new JedisPool(config, "127.0.0.1", 6379, 1000 * 10, "123456"); Jedis jedis = jedisPool.getResource(); jedis.flushDB(); jedis.set("name", "XXX"); jedis.set("age", "18"); Transaction transaction = jedis.multi(); transaction.incr("name"); transaction.incr("age"); List<Object> exec = transaction.exec(); System.out.println(exec); jedis.close(); jedisPool.destroy(); }
5 Redis持久化
持久化(持久層,dao層,mapper層):把數據保存到磁盤的過程就叫持久化
Redis支持內存和磁盤存儲,磁盤存儲提供兩種方案:
rdb方式:save 1 1 最快的保存方法,1s中發生一次變化,如果保存數據在1s內完成,容易造成數據丟失,丟失1s數據。
aof方式:開啟 appendonly yes ,在操作的時候,把數據寫到日志文件,在啟動的時候 ,恢復日志文件(日志方式)。
6 Redis的淘汰策略
什么時候才淘汰數據: --》內存到一定極限的時候,這個時候,需要淘汰數據
淘汰一些數據,達到redis數據都是有效的。選擇合適的淘汰策略進行淘汰。
volatile-lru:從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰
volatile-ttl:從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰
volatile-random:從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰
allkeys-lru:從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
allkeys-random:從數據集(server.db[i].dict)中任意選擇數據淘汰
no-enviction(驅逐):禁止驅逐數據
redis 確定驅逐某個鍵值對后,會刪除這個數據並,並將這個數據變更消息發布到本地(AOF 持久化)和從機(主從連接)。
lru: 最近最少使用 -- 常用 (統計次數)
ttl: 將要過期中淘汰 --也可以 (統計時間)
random:隨機數據 --這個數據就沒有那么重要 (隨機)