redis緩存數據庫詳解(—)

今日內容

1. redis
	1. 概念
	2. 下載安裝
	3. 命令操做
		1. 數據結構
	4. 持久化操做
	5. 使用Java客戶端操做redis
複製代碼

一、Redis簡介

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


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

		1.1.1.	NOSQL和關係型數據庫比較
			優勢:
				1)成本:nosql數據庫簡單易部署,基本都是開源軟件,不須要像使用oracle那樣花費大量成本購買使用,相比關係型數據庫價格便宜。
				2)查詢速度:nosql數據庫將數據存儲於緩存之中,關係型數據庫將數據存儲在硬盤中,天然查詢速度遠不及nosql數據庫。
				3)存儲數據的格式:nosql的存儲格式是key,value形式、文檔形式、圖片形式等等,因此能夠存儲基礎類型以及對象或者是集合等各類格式,而數據庫則只支持基礎類型。
				4)擴展性:關係型數據庫有相似join這樣的多表查詢機制的限制致使擴展很艱難。

			缺點:
				1)維護的工具和資料有限,由於nosql是屬於新的技術,不能和關係型數據庫10幾年的技術同日而語。
				2)不提供對sql的支持,若是不支持sql這樣的工業標準,將產生必定用戶的學習和使用成本。
				3)不提供關係型數據庫對事務的處理。

		1.1.2.	非關係型數據庫的優點:
			1)性能NOSQL是基於鍵值對的,能夠想象成表中的主鍵和值的對應關係,並且不須要通過SQL層的解析,因此性能很是高。
			2)可擴展性一樣也是由於基於鍵值對,數據之間沒有耦合性,因此很是容易水平擴展。

		1.1.3.	關係型數據庫的優點:
			1)複雜查詢能夠用SQL語句方便的在一個表以及多個表之間作很是複雜的數據查詢。
			2)事務支持使得對於安全性能很高的數據訪問要求得以實現。對於這兩類數據庫,對方的優點就是本身的弱勢,反之亦然。

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

	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分離
複製代碼

二、下載安裝

1. 官網:https://redis.io
	2. 中文網:http://www.redis.net.cn/
	3. 解壓直接可使用:
		* redis.windows.conf:配置文件
		* redis-cli.exe:redis的客戶端
		* redis-server.exe:redis服務器端
複製代碼

三、 命令操做

1. redis的數據結構:
		* redis存儲的是:key,value格式的數據,其中key都是字符串,value有5種不一樣的數據結構
			* value的數據結構:
				1) 字符串類型 string
				2) 哈希類型 hash : map格式  
				3) 列表類型 list : linkedlist格式。支持重複元素
				4) 集合類型 set  : 不容許重複元素
				5) 有序集合類型 sortedset:不容許重複元素,且元素有順序
	
	2. 字符串類型 string
		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
	3. 哈希類型 hash
		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
複製代碼

4. 列表類型 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: 刪除列表最右邊的元素,並將元素返回


	5. 集合類型 set : 不容許重複元素
		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
	6. 有序集合類型 sortedset:不容許重複元素,且元素有順序.每一個元素都會關聯一個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

	7. 通用命令
		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	 : 不進行持久化
複製代碼

五、 Java客戶端 Jedis

* Jedis: 一款java操做redis數據庫的工具(至關於jdbc).
	* 使用步驟:
		1. 下載jedis的jar包
		2. 使用
			//1. 獲取鏈接
    		Jedis jedis = new Jedis("localhost",6379);
   			//2. 操做
   			jedis.set("username","zhangsan");
    		//3. 關閉鏈接
    		jedis.close();

	
	* Jedis操做各類redis中的數據結構
		1) 字符串類型 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();

		2) 哈希類型 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();


		3) 列表類型 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();


		4) 集合類型 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();
		5) 有序集合類型 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();
			    }
			}
複製代碼

redis五大數據類型php

redis的數據結構:
			* redis存儲的是:key,value格式的數據,其中key都是字符串,value有5種不一樣的數據結構
				* value的數據結構:
					1) 字符串類型 string
					2) 哈希類型 hash : map格式  
					3) 列表類型 list : linkedlist格式。支持重複元素
					4) 集合類型 set  : 不容許重複元素
					5) 有序集合類型 sortedset:不容許重複元素,且元素有順序
		
複製代碼

七、存儲字符串

代碼示例java

package com.baoji.jedis.test;

import com.baoji.jedis.util.JedisPoolUtils;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.List;
import java.util.Map;
import java.util.Set;


/*
        String字符串的方法演示
     */
    @Test
    public void test1() {
        //一、獲取鏈接
        Jedis jedis = new Jedis("localhost",6379);  //建立Jedis對象,若是使用空參構造,默認值:"localhost",6379端口
        //二、存儲操做
        jedis.set("username","zhangsan");
        //三、獲取操做
        String username = jedis.get("username");
        System.out.println(username);

        //可使用setex()方法能夠存儲指定過時時間的 key value
        jedis.setex("acticeCode",20,"abcd##");// 將acticeCode:abcd##鍵值對存入redis,而且20秒後自動刪除該鍵值對
        //三、關閉鏈接
        jedis.close();
    }
複製代碼

八、存儲HashMap

/*
        hash map的方法演示
     */
    @Test
    public void test2() {
        //一、獲取鏈接
        Jedis jedis = new Jedis();  //建立Jedis對象,若是使用空參構造,默認值:"localhost",6379端口
        //二、hash存儲操做
       jedis.hset("user","name","zhangsan");
        jedis.hset("user","age","20");
        jedis.hset("user","gender","female");
        //三、獲取hash操做
       String name = jedis.hget("user","name");
        System.out.println(name);

        //四、獲取全部hash操做
        Map<String,String> user = jedis.hgetAll("user");
        //遍歷map採用keyset方式(獲取全部的鍵)
        Set<String> keys = user.keySet();
        //根據鍵獲取全部的值
        for (String key:keys) {
            //獲取值操做
            String value = user.get(key);
            System.out.println(key+":"+value);
        }

        //可使用setex()方法能夠存儲指定過時時間的 key value
        jedis.setex("acticeCode",20,"abcd##");// 將acticeCode:abcd##鍵值對存入redis,而且20秒後自動刪除該鍵值對
        //三、關閉鏈接
        jedis.close();
    }
複製代碼

九、存儲list列表

/*
        list 列表的方法演示
     */
    @Test
    public void test3() {
        //一、獲取鏈接
        Jedis jedis = new Jedis();  //建立Jedis對象,若是使用空參構造,默認值:"localhost",6379端口
        //二、list存儲操做
        jedis.lpush("mylist","a","b","c");// 從左邊存儲[c,b,a]
        jedis.rpush("mylist","a","b","c"); //從右邊存儲[a,b,c]
        //三、list範圍獲取
        List<String> list = jedis.lrange("mylist",0,-1);//獲取全部mylist鍵下的值 -1表明全部
        System.out.println(list);

        //四、彈出元素
        String element1 = jedis.lpop("mylist");//左邊彈出第一個元素
        System.out.println(element1);
        String element2 = jedis.lpop("mylist");//右邊彈出第一個元素
        System.out.println(element2);

        //獲取範圍
        List<String> list1 = jedis.lrange("mylist",0,-1);
        System.out.println(list1);

        //可使用setex()方法能夠存儲指定過時時間的 key value
       //jedis.setex("acticeCode",20,"abcd##");// 將acticeCode:abcd##鍵值對存入redis,而且20秒後自動刪除該鍵值對
        //三、關閉鏈接
        jedis.close();
    }
複製代碼

十、存儲set集合

/*
        set 集合的方法演示
     */
    @Test
    public void test4() {
        //一、獲取鏈接
        Jedis jedis = new Jedis();  //建立Jedis對象,若是使用空參構造,默認值:"localhost",6379端口
        //二、set存儲操做
       jedis.sadd("myset","java","php","c#");
        //三、set獲取操做
        Set<String> set = jedis.smembers("myset");
        System.out.println(set);
        //可使用setex()方法能夠存儲指定過時時間的 key value
        //jedis.setex("acticeCode",20,"abcd##");// 將acticeCode:abcd##鍵值對存入redis,而且20秒後自動刪除該鍵值對
        //三、關閉鏈接
        jedis.close();
    }
複製代碼

十一、存儲sortedset 有序集合

@Test
    public void test5() {
        //一、獲取鏈接
        Jedis jedis = new Jedis();  //建立Jedis對象,若是使用空參構造,默認值:"localhost",6379端口
        //二、set存儲操做
        jedis.zadd("mySortedSet",89,"張三");
        jedis.zadd("mySortedSet",74,"李四");
        jedis.zadd("mySortedSet",95,"王五");
        //三、sortedset獲取操做
       Set<String> mySortedSet= jedis.zrange("mySortedSet",0,-1);
        System.out.println(mySortedSet);
        //可使用setex()方法能夠存儲指定過時時間的 key value
        //jedis.setex("acticeCode",20,"abcd##");// 將acticeCode:abcd##鍵值對存入redis,而且20秒後自動刪除該鍵值對
        //三、關閉鏈接
        jedis.close();
    }

    /*
複製代碼

十二、Jedis Pool 使用

/*
        jedis鏈接池的使用演示
     */
    @Test
    public void test6() {
        //0、建立一個配置對象
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(50);//得到最大容許鏈接數
        config.setMaxIdle(10);//得到最大空閒鏈接
        //一、建立鏈接池對象
        JedisPool jedisPool = new JedisPool(config,"localhost",6379);
        //二、得到鏈接 getResource()
        Jedis jedis = jedisPool.getResource();
        //三、操做
        jedis.set("name","zhangsan");
       String value = jedis.get("name");
        System.out.println(value);
        //四、關閉鏈接
        jedis.close();
    }
複製代碼

1三、Jedis Pool工具類使用

/*
        jedis鏈接池的工具類使用演示
     */
    @Test
    public void test7() {
        //一、經過鏈接池工具類獲取
        Jedis jedis = JedisPoolUtils.getJedis();
        //二、操做jedis
        jedis.set("name","lisi");
        String value = jedis.get("name");
        System.out.println(value);
        //三、經過鏈接池工具類關閉
        JedisPoolUtils.closeJedis();
    }
}
複製代碼

關係型數據庫和非關係型數據庫區別:


redis是一款非關係型數據庫,通常存放在數據庫中的數據,都存放在計算機硬盤的文件中,每次訪問須要讀取文件,性能比較低,可是很安全,數據不會由於關閉服務器或者關機致使丟失。redis緩存的數據存放在內存中,用戶訪問數據直接在內存中讀取數據,性能比較高,可是數據可能會丟失,因此不太安全,通常非關係型數據庫和關係型數據庫結合使用。c++

使用場景:項目中不須要常常修改的數據,能夠把數據庫的數據拿出來存放在redis緩存中,沒必要要用戶每次提交請求都要訪問數據庫,形成數據庫的開銷比較大,也提升性能。git


寫在最後

推薦做者的Github地址: github.com/Lmobjectgithub

相關文章
相關標籤/搜索