概述
簡介
NoSQL : Not only SQL,泛指一切非關(guān)系型數(shù)據(jù)庫
關(guān)系型數(shù)據(jù)庫:指以表的形式來保存數(shù)據(jù)庫,以鍵/表的形式維護數(shù)據(jù)庫之前的關(guān)系。如 Oracle、DB2、Microsoft SQL Server、Microsoft Access、MySQL
非關(guān)系型數(shù)據(jù)庫:泛指 關(guān)系型數(shù)據(jù)庫之外其它類型的數(shù)據(jù)庫 。如 NoSql、Cloudant等
關(guān)系型數(shù)據(jù)庫的缺點
- 高并發(fā)問題:海量的請求同時訪問數(shù)據(jù)庫
- 高性能問題:數(shù)據(jù)量越來越大,需要從海量的數(shù)據(jù)量瞬間訪問/操作某一些數(shù)據(jù)
- 高擴展問題:數(shù)據(jù)庫的集群,數(shù)據(jù)的遷移和移植
非關(guān)系型數(shù)據(jù)庫的優(yōu)點
- 實現(xiàn)高性能要求:數(shù)據(jù)之間沒有關(guān)系,所以數(shù)據(jù)的存取效率是非常高
- 數(shù)據(jù)結(jié)構(gòu)非常靈活:不以表的形式保存數(shù)據(jù),可以以任何適合的格式來保存數(shù)據(jù)
- 高擴展的優(yōu)點:可以非常靈活進行數(shù)據(jù)移植
web 應(yīng)用開發(fā)中非關(guān)系型數(shù)據(jù)庫的使用
仍然是以關(guān)系型數(shù)據(jù)庫來持久化報錯數(shù)據(jù),可以維護數(shù)據(jù)之間的業(yè)務(wù)關(guān)系。非關(guān)系型數(shù)據(jù)庫作為補充。可以用來提升數(shù)據(jù)庫的存取效率。
通常把 Redis 數(shù)據(jù)庫與作為數(shù)據(jù)緩存,緩存了一些經(jīng)常讀取,但不經(jīng)常修改的數(shù)據(jù)。列如:商品的分類信息,可以放在在緩存里。頁面需要顯示分類的時候,從緩存里讀取,速度或比較快,可以有效提高 web 應(yīng)用的訪問性能。
Redis
C編寫的免費開源,以 key-value 存取數(shù)據(jù)的非關(guān)系型數(shù)據(jù)庫,把數(shù)據(jù)存儲到內(nèi)存中,而不是磁盤中,有非常高的讀寫性能。
Redis 的端口:6379 merz
操作Redis
Redis 的數(shù)據(jù)類型
以 key-value 保存數(shù)據(jù)
key:始終是字符串。通常來說,key的長度不要超過1024個字節(jié),否則會影響數(shù)據(jù)的讀寫性能。
value:數(shù)據(jù)類型是五種 :
- string:字符串類型,一個string可以保存512M數(shù)據(jù)
- hash:哈希列表,類似于 HashMap,一個hash可以保存 2^23-1個數(shù)據(jù)
- List:列表類型,類似于 LinkedList, 2^23-1
- set:無序不重復的數(shù)據(jù)集合,類似于Set, 2^23-1
- zset:(sorted set)有序不重復的數(shù)據(jù)集合, 2^23-1
Redis 的數(shù)據(jù)操作
-
操作 string
設(shè)置數(shù)據(jù):set key value 比如: set username zhangsan 獲取數(shù)據(jù): get key 比如: get username 刪除數(shù)據(jù): del key 比如: del username
-
操作 hash
添加數(shù)據(jù): hset key field value 比如: hset user username coco 獲取數(shù)據(jù): hget key field 比如: hget user username 刪除數(shù)據(jù): hdel key field 比如: hdel user username 獲取所有: hgetall key 比如: hgetall user
-
操作 List
添加數(shù)據(jù): 從左邊壓入數(shù)據(jù): lpush key value1 value2... 從右邊壓入數(shù)據(jù):rpush key value1 value2... 彈出數(shù)據(jù): 從左邊彈出數(shù)據(jù):lpop key 從右邊彈出數(shù)據(jù):rpop key 查看數(shù)據(jù): lrange key 0 -1 其中:-1表示最后一個數(shù)據(jù)
-
操作 Set
添加數(shù)據(jù): sadd key value 隨機取出一個數(shù)據(jù): srandmember key 查看數(shù)據(jù): smembers key 刪除數(shù)據(jù): srem key member 多集合之間的運算: 交集: sinter key1 key2 并集: sunion key1 key2 差集: sdiff key1 key2
-
通用的 key 操作
查詢key: keys表達式 比如:keys *, keys myset? 刪除key: del key 判斷key是否存在: exists key 獲取key的類型: type key
Jedis
Redis 在 web 應(yīng)用開發(fā)中,是作為緩存來使用的,通過 Java 程序來操作 Redis 數(shù)據(jù)。
Jedis 操作 Redis 數(shù)據(jù)庫需要的 jar 包:
Jedis-*.jar
-
common-pool*.jar u
連接池使用的
操作步驟:
- 獲取連接 Jedis 對象
- 操作 Jedis
- 釋放資源,關(guān)閉 Jedis
Jedis 的 API
構(gòu)造方法: Jedis(String host,int port)
常用方法: 方法名和命令名稱一致
設(shè)置string數(shù)據(jù): set(String key,String value)
獲取string數(shù)據(jù): get(String key)
刪除string數(shù)據(jù): del(String key)
從左邊向list添加一個數(shù)據(jù): lpush(String key,String value)
關(guān)閉連接: jedis.close();
Jedis 操作示例
@Test
public void demo1(){
//1. 創(chuàng)建 Jedis 連接對象
Jedis jedis = new Jedis("localhost",6379);
//2. 操作 Redis 數(shù)據(jù)庫
//jedis.set("username","zhangsan");
String username = jedis.get("username");
System.out.println(username);
//3. 關(guān)閉連接對象
jedis.close();
}
Jedis 連接池的 API
連接池的構(gòu)造方法:
JedisPool(String host,int port) 使用默認配置的連接池
JedisPool(JedisPoolConfig config,String host,int port) 使用自定義的連接池
連接池配置信息對象
無參構(gòu)造: JedisPoolConfig()
常用方法:
setMaxTotal(int maxTotal) 設(shè)置最大連接數(shù)
setMaxIdle(int maxIdle) 設(shè)置最大空閑連接數(shù)
從連接池 JedisPool 里獲取連接:
Jedis jedis = pool.getResource()
Jedis 連接池示例
//1. 創(chuàng)建一個連接池配置信息對象,設(shè)置連接池的參數(shù)信息
//2. 使用配置信息對象,創(chuàng)建連接池對象
//3. 從連接池里獲取連接
@Test
public void demo2() {
// 創(chuàng)建一個連接池的配置對象
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(30); //設(shè)置連接池里最多有30個連接
jedisPoolConfig.setMaxIdle(10); //設(shè)置連接池里最多有10個空閑連接
// 使用配置信息對象,創(chuàng)建連接池對象
JedisPool jedisPool = new JedisPool(jedisPoolConfig, "localhost", 6379);
//從連接池獲取連接對象
Jedis jedis = jedisPool.getResource();
//操作 Redis 數(shù)據(jù)庫
String username = jedis.get("username");
System.out.println(username);
//關(guān)閉連接對象
jedis.close();
}
封裝 jedis 工具類 : JedisUtils
//1.JedisUtils
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.util.ResourceBundle;
public class JedisUtils {
private static JedisPool pool;
private static String host;
private static int port;
private static int maxTotal;
private static int maxIdle;
static{
//加載資源文件
ResourceBundle bundle = ResourceBundle.getBundle("jedis");
host = bundle.getString("host");
port = Integer.parseInt(bundle.getString("port"));
maxTotal = Integer.parseInt(bundle.getString("maxTotal"));
maxIdle = Integer.parseInt(bundle.getString("maxIdle"));
//創(chuàng)建連接池配置信息
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(maxTotal);
config.setMaxIdle(maxIdle);
//創(chuàng)建連接池對象
pool = new JedisPool(config, host, port);
}
/**
* 獲取Jedis連接
* @return Jedis對象
*/
public static Jedis getJedis(){
return pool.getResource();
}
/**
* 關(guān)閉Jedis連接
* @param jedis 要關(guān)閉的Jedis連接對象
*/
public static void close(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
/**
* 設(shè)置緩存
* @param key 緩存的key
* @param value 緩存的value
*/
public static void setCache(String key, String value){
Jedis jedis = null;
try {
jedis = getJedis();
jedis.set(key, value);
} catch (Exception e) {
System.out.println("設(shè)置緩存數(shù)據(jù)失敗:["+key+":"+value+"]");
} finally {
//關(guān)閉連接
if (jedis != null) {
jedis.close();
}
}
}
/**
* 獲取緩存
* @param key 緩存的key
* @return 緩存的value
*/
public static String getCache(String key) {
Jedis jedis = null;
try {
jedis = getJedis();
return jedis.get(key);
} catch (Exception e) {
System.out.println("獲取緩存失敗:" + key);
} finally {
//關(guān)閉連接
if (jedis != null) {
jedis.close();
}
}
return null;
}
}
//2. 配置文件 jedis.properties
host=localhost
port=6379
maxTotal=30
maxIdle=10
//3.test
@Test
public void demo2() {
JedisUtils.setCache("username", "coco1");
}
@Test
public void demo3() {
String username = JedisUtils.getCache("username");
System.out.println(username);
}
持久化機制
? Redis數(shù)據(jù)庫是把數(shù)據(jù)保存在了內(nèi)存當中,那么如果Redis服務(wù)關(guān)閉,就需要把內(nèi)存里的數(shù)據(jù)進行持久化保存,所以Redis本身提供了持久化機制:在某些時候把內(nèi)存里的數(shù)據(jù)保存到磁盤文件上。
? Redis提供了兩種持久化機制:RDB模式 和 AOF模式。
RDB 模式
RDB 模式:快照模式,默認是開啟狀態(tài)的。
定期把 Redis 內(nèi)存中的數(shù)據(jù),生成快照文件,保存到磁盤文件上。默認生成的文件:dump.rdb,默認保存在 Redis 安裝目錄中
RDB 模式的相關(guān)配置,在 redis.conf里
save 900 1 表示:如果數(shù)據(jù)變更1次,那么900秒生成一次快照文件
save 300 10 表示:如果數(shù)據(jù)變更10次,那么300秒生成一次快照文件
save 60 10000 表示:如果數(shù)據(jù)變更1000次,那么10000秒生成一次快照文件
dbfilename dump.rdb 默認生成的快照文件名稱
dir ./ 表示生成的快照文件,保存到redis-server的當前目錄
AOF 模式
AOF模式:append only file模式,默認是關(guān)閉的。
如果我們在Redis里執(zhí)行數(shù)據(jù)的變更,那么每次變量,Redis都會把執(zhí)行的命令追加到一個文件里。等Redis重啟、需要恢復數(shù)據(jù)的時候,讀取文件里所有的命令,按順序重新構(gòu)建Redis的數(shù)據(jù)。
如果開啟了AOF模式,Redis會把數(shù)據(jù)變更的命令保存到了appendonly.aof,默認在Redis的安裝目錄里。這些信息可以通過修改redis.conf更改配置:
appendonly no AOF模式的開關(guān),默認是關(guān)閉狀態(tài),如果要使用,需要手動更改成yes。需要重新Redis
appendfilename "appendonly.aof" 默認生成的文件名稱appendonly.aof
# appendfsync always 每次數(shù)據(jù)變更,都保存變更的命令到aof文件里
appendfsync everysec 每秒保存一次
# appendfsync no 不保存
RDB模式和AOF模式的優(yōu)缺點
RDB模式:默認開啟,性能高;但是可能會丟失數(shù)據(jù)
AOF模式:默認關(guān)閉,比較安全,丟失數(shù)據(jù)的可能性小;影響性能。
Redis在web應(yīng)用里的使用方式
web應(yīng)用里的數(shù)據(jù)最終還是必須要保存到關(guān)系型數(shù)據(jù)庫里,Redis作為數(shù)據(jù)的緩存使用。