【大數據筆記】Redis

2020-08-12 10:29:22

Redis

概念: redis是一款高效能的NOSQL系列的非關係型數據庫

1.什麼是NOSQL

NoSQL(NoSQL = Not Only SQL),意即「不僅僅是SQL」,是一項全新的數據庫理念,泛指非關係型的數據庫。
隨着網際網路web2.0網站的興起,傳統的關係數據庫在應付web2.0網站,特別是超大規模和高併發的SNS型別的web2.0純動態網站已經顯得力不從心,暴露了很多難以克服的問題,而非關係型的數據庫則由於其本身的特點得到了非常迅速的發展。NoSQL數據庫的產生就是爲了解決大規模數據集合多重數據種類帶來的挑戰,尤其是大數據應用難題。

  • NOSQL和關係型數據庫比較

    • 優點:

      • 成本:nosql數據庫簡單易部署,基本都是開源軟體,不需要像使用oracle那樣花費大量成本購買使用,相比關係型數據庫價格便宜。
      • 查詢速度:nosql數據庫將數據儲存於快取之中,關係型數據庫將數據儲存在硬碟中,自然查詢速度遠不及nosql數據庫。
      • 儲存數據的格式:nosql的儲存格式是key,value形式、文件形式、圖片形式等等,所以可以儲存基礎型別以及物件或者是集合等各種格式,而數據庫則只支援基礎型別。
      • 擴充套件性:關係型數據庫有類似join這樣的多表查詢機制 機製的限制導致擴充套件很艱難。
    • 缺點:

      • 維護的工具和資料有限,因爲nosql是屬於新的技術,不能和關係型數據庫10幾年的技術同日而語。
      • 不提供對sql的支援,如果不支援sql這樣的工業標準,將產生一定使用者的學習和使用成本。
      • 不提供關係型數據庫對事務的處理。
  • 非關係型數據庫的優勢:

    • 效能NOSQL是基於鍵值對的,可以想象成表中的主鍵和值的對應關係,而且不需要經過SQL層的解析,所以效能非常高。
    • 可延伸性同樣也是因爲基於鍵值對,數據之間沒有耦合性,所以非常容易水平擴充套件。
  • 關係型數據庫的優勢:

    • 複雜查詢可以用SQL語句方便的在一個表以及多個表之間做非常複雜的數據查詢。
    • 事務支援使得對於安全效能很高的數據存取要求得以實現。對於這兩類數據庫,對方的優勢就是自己的弱勢,反之亦然。
  • 總結

    • 關係型數據庫與NoSQL數據庫並非對立而是互補的關係,即通常情況下使用關係型數據庫,在適合使用NoSQL的時候使用NoSQL數據庫,
    • 讓NoSQL數據庫對關係型數據庫的不足進行彌補。
    • 一般會將數據儲存在關係型數據庫中,在nosql數據庫中備份儲存關係型數據庫的數據

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
    • 典型應用:社羣網路
    • 數據模型:圖結構
    • 優勢:利用圖結構相關演算法。
    • 劣勢:需要對整個圖做計算才能 纔能得出結果,不容易做分佈式的叢集方案。

3.什麼是Redis

Redis是用C語言開發的一個開源的高效能鍵值對(key-value)數據庫,官方提供測試數據,50個併發執行100000個請求,讀的速度是110000次/s,寫的速度是81000次/s ,且Redis通過提供多種鍵值數據型別來適應不同場景下的儲存需求,目前爲止Redis支援的鍵值數據型別如下:

  • 字串型別 string
  • 雜湊型別 hash
  • 列表型別 list
  • 集合型別 set
  • 有序集合型別 sortedset
redis的應用場景
  • 快取(數據查詢、短連線、新聞內容、商品內容等等)
  • 聊天室的線上好友列表
  • 任務佇列。(秒殺、搶購、12306等等)
  • 應用排行榜
  • 網站存取統計
  • 數據過期處理(可以精確到毫秒
  • 分佈式叢集架構中的session分離

4.下載安裝

  • 官網:https://redis.io
  • 中文網:http://www.redis.net.cn/
  • 解壓直接可以使用:
    • redis.windows.conf:組態檔
    • redis-cli.exe:redis的用戶端
    • redis-server.exe:redis伺服器端

5. 命令操作

① redis的數據結構:

redis儲存的是:key,value格式的數據,其中key都是字串,value有5種不同的數據結構

  • value的數據結構:
    • 字串型別 string
    • 雜湊型別 hash : map格式
    • 列表型別 list : linkedlist格式。支援重複元素
    • 集合型別 set : 不允許重複元素
    • 有序集合型別 sortedset:不允許重複元素,且元素有順序
② 字串型別 string
  • 儲存: set key value
    127.0.0.1:6379> set username zhangsan
    OK
  • 獲取: get key
    127.0.0.1:6379> get username
    「zhangsan」
  • 刪除: del key
    127.0.0.1:6379> del age
    (integer) 1
③雜湊型別 hash
  • 儲存: 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

  • 獲取:

    • 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」
  • 刪除: hdel key field
    127.0.0.1:6379> hdel myhash username
    (integer) 1

④列表型別 list:可以新增一個元素到列表的頭部(左邊)或者尾部(右邊)
  • 新增:
    • lpush key value: 將元素加入列表左表

    • 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

  • 獲取:
    • lrange key start end :範圍獲取127.0.0.1:6379> lrange myList 0 -1
      1) 「b」
      2) 「a」
      3) 「c」
  • 刪除:
    • lpop key: 刪除列表最左邊的元素,並將元素返回
    • rpop key: 刪除列表最右邊的元素,並將元素返回
⑤集合型別 set : 不允許重複元素
  • 儲存:sadd key value
    127.0.0.1:6379> sadd myset a
    (integer) 1
    127.0.0.1:6379> sadd myset a
    (integer) 0
  • 獲取:smembers key:獲取set集閤中所有元素
    127.0.0.1:6379> smembers myset
    1) 「a」
  • 刪除:srem key value:刪除set集閤中的某個元素
    127.0.0.1:6379> srem myset a
    (integer) 1
⑥有序集合型別 sortedset:不允許重複元素,且元素有順序.每個元素都會關聯一個double型別的分數。redis正是通過分數來爲集閤中的成員進行從小到大的排序。
  • 儲存: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
  • 獲取: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」
  • 刪除:zrem key value
    127.0.0.1:6379> zrem mysort lisi
    (integer) 1
⑦通用命令
  • keys * : 查詢所有的鍵
  • type key : 獲取鍵對應的value的型別
  • del key:刪除指定的key value

6. 持久化

  • edis是一個記憶體數據庫,當redis伺服器重新啓動,獲取電腦重新啓動,數據會丟失,我們可以將redis記憶體中的數據持久化儲存到硬碟的檔案中。
  • redis持久化機制 機製:
    • RDB:預設方式,不需要進行設定,預設就使用這種機制 機製
      在一定的間隔時間中,檢測key的變化情況,然後持久化數據

      • 編輯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
      
      • 重新啓動redis伺服器,並指定組態檔名稱
        D:\JavaWeb2018\day23_redis\資料\redis\windows-64\redis-2.8.9>redis-server.exe redis.windows.conf
    • AOF:日誌記錄的方式,可以記錄每一條命令的操作。可以每一次命令操作後,持久化數據

      • 編輯redis.windwos.conf檔案
      appendonly no(關閉aof) --> appendonly yes (開啓aof)
      # appendfsync always : 每一次操作都進行持久化
      	appendfsync everysec : 每隔一秒進行一次持久化
      # appendfsync no	 : 不進行持久化
      

7. Java用戶端 Jedis

Jedis: 一款java操作redis數據庫的工具.
使用步驟:
  • 下載jedis的jar包
  • 使用
//1. 獲取連線
Jedis jedis = new Jedis("localhost",6379);
//2. 操作
jedis.set("username","zhangsan");
//3. 關閉連線
 jedis.close();
edis操作各種redis中的數據結構
  • 字串型別 string
    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();
  • 雜湊型別 hash : map格式
    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();

  • 列表型別 list : linkedlist格式。支援重複元素
    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();
  • 集合型別 set : 不允許重複元素
    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();

  • 有序集合型別 sortedset:不允許重複元素,且元素有順序
    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();
jedis連線池: JedisPool
  • 使用:
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();
			
  • 連線池工具類
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();
				    }
				}