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