
[TOC]
第一章:redis
1.1-什么是NoSql
概述
NoSQL,泛指非關系型的數(shù)據(jù)庫。隨著互聯(lián)網(wǎng)web2.0網(wǎng)站的興起,傳統(tǒng)的關系數(shù)據(jù)庫在處理web2.0網(wǎng)站,特別是超大規(guī)模和高并發(fā)的SNS類型的web2.0純動態(tài)網(wǎng)站已經(jīng)顯得力不從心,出現(xiàn)了很多難以克服的問題,而非關系型的數(shù)據(jù)庫則由于其本身的特點得到了非常迅速的發(fā)展。NoSQL數(shù)據(jù)庫的產生就是為了解決大規(guī)模數(shù)據(jù)集合多重數(shù)據(jù)種類帶來的挑戰(zhàn),尤其是大數(shù)據(jù)應用難題。
主流的Nosql
鍵值(Key-Value)存儲數(shù)據(jù)庫
- 相關產品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
- 典型應用: 內容緩存,主要用于處理大量數(shù)據(jù)的高訪問負載。
- 數(shù)據(jù)模型: 一系列鍵值對
- 優(yōu)勢: 快速查詢
- 劣勢: 存儲的數(shù)據(jù)缺少結構化
列存儲數(shù)據(jù)庫
- 相關產品:Cassandra, HBase, Riak
- 典型應用:分布式的文件系統(tǒng)
- 數(shù)據(jù)模型:以列簇式存儲,將同一列數(shù)據(jù)存在一起
- 優(yōu)勢:查找速度快,可擴展性強,更容易進行分布式擴展
- 劣勢:功能相對局限
文檔型數(shù)據(jù)庫
- 相關產品:CouchDB、MongoDB
- 典型應用:Web應用(與Key-Value類似,Value是結構化的)
- 數(shù)據(jù)模型: 一系列鍵值對
- 優(yōu)勢:數(shù)據(jù)結構要求不嚴格
- 劣勢: 查詢性能不高,而且缺乏統(tǒng)一的查詢語法
圖形(Graph)數(shù)據(jù)庫
相關數(shù)據(jù)庫:Neo4J、InfoGrid、Infinite Graph
典型應用:社交網(wǎng)絡
數(shù)據(jù)模型:圖結構
優(yōu)勢:利用圖結構相關算法
劣勢:需要對整個圖做計算才能得出結果,不容易做分布式的集群方案。
1.2-NoSql和關系型數(shù)據(jù)庫
NOSQL
優(yōu)點:
- 成本:nosql數(shù)據(jù)庫簡單易部署,基本都是開源軟件,不需要像使用oracle那樣花費大量成本購買使用,相比關系型數(shù)據(jù)庫價格便宜。
- 查詢速度:nosql數(shù)據(jù)庫將數(shù)據(jù)存儲于緩存之中,關系型數(shù)據(jù)庫將數(shù)據(jù)存儲在硬盤中,自然查詢速度遠不及nosql數(shù)據(jù)庫。
- 存儲數(shù)據(jù)的格式:nosql的存儲格式是key,value形式、文檔形式、圖片形式等等,所以可以存儲基礎類型以及對象或者是集合等各種格式,而數(shù)據(jù)庫則只支持基礎類型。
- 擴展性:關系型數(shù)據(jù)庫有類似join這樣的多表查詢機制的限制導致擴展很艱難
缺點:
- 維護的工具和資料有限,因為nosql是屬于新的技術,不能和關系型數(shù)據(jù)庫10幾年的技術同日而語。
- 不提供對sql的支持,如果不支持sql這樣的工業(yè)標準,將產生一定用戶的學習和使用成本。
- 不提供關系型數(shù)據(jù)庫對事務的處理。
非關系型數(shù)據(jù)庫的優(yōu)勢
- 性能NOSQL是基于鍵值對的,可以想象成表中的主鍵和值的對應關系,而且不需要經(jīng)過SQL層的解析,所以性能非常高。
- 可擴展性同樣也是因為基于鍵值對,數(shù)據(jù)之間沒有耦合性,所以非常容易水平擴展。
關系型數(shù)據(jù)庫的優(yōu)勢
- 復雜查詢可以用SQL語句方便的在一個表以及多個表之間做非常復雜的數(shù)據(jù)查詢。
- 事務支持使得對于安全性能很高的數(shù)據(jù)訪問要求得以實現(xiàn)。對于這兩類數(shù)據(jù)庫,對方的優(yōu)勢就是自己的弱勢,反之亦然。
總結
關系型數(shù)據(jù)庫與NoSQL數(shù)據(jù)庫并非對立而是互補的關系,即通常情況下使用關系型數(shù)據(jù)庫,在適合使用NoSQL的時候使用NoSQL數(shù)據(jù)庫,讓NoSQL數(shù)據(jù)庫對關系型數(shù)據(jù)庫的不足進行彌補。
一般會將數(shù)據(jù)存儲在關系型數(shù)據(jù)庫中,在nosql數(shù)據(jù)庫中備份存儲關系型數(shù)據(jù)庫的數(shù)據(jù)。
1.3-Redis
概述
REmote DIctionary Server(Redis) redis是一個key-value存儲系統(tǒng)(nosql非關系型數(shù)據(jù)庫)。
它支持存儲的value類型相對更多,包括
- string(字符串)
- list(鏈表)
- set(集合)
- zset(sorted set --有序集合)
- hash(哈希類型) 。
為了保證效率,數(shù)據(jù)都是緩存在內存中。 redis會周期性的把更新的數(shù)據(jù)寫入磁盤或者把修改操作寫入追加的記錄文件,并且在此基礎上實現(xiàn)了master-slave(主從)同步 。
應用場景
緩存(數(shù)據(jù)查詢、短連接、新聞內容、商品內容等等)
聊天室的在線好友列表
任務隊列。(秒殺、搶購、12306等等)
應用排行榜
網(wǎng)站訪問統(tǒng)計
數(shù)據(jù)過期處理(可以精確到毫秒
分布式集群架構中的session分離
1.4-Redis下載和安裝
下載
官方網(wǎng)站:https://redis.io
中文網(wǎng)站:http://www.redis.cn
安裝
直接解壓即可

使用
啟動服務端

啟動客戶端

1.5-Redis常用命令操作
以下命令是對Reids數(shù)據(jù)庫中的不同類型的數(shù)據(jù)的操作相關
操作字符串String
命令:
- 存儲:
set key value - 獲?。?code>get key
- 刪除:
del key
代碼:
127.0.0.1:6379> set name LiLei
OK
127.0.0.1:6379> get name
"LiLei"
127.0.0.1:6379> del name
(integer) 1
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379>
操作鏈表List
命令:
- 添加
-
lpush key value: 將元素加入列表左表 -
rpush key value:將元素加入列表右邊
-
- 獲取
-
lrange key start end:范圍獲取
-
- 刪除
-
lpop key: 刪除列表最左邊的元素,并將元素返回 -
rpop key: 刪除列表最右邊的元素,并將元素返回
-
代碼:
127.0.0.1:6379> lpush names Andy
(integer) 1
127.0.0.1:6379> lpush names Lucy
(integer) 2
127.0.0.1:6379> rpush names Rose
(integer) 3
127.0.0.1:6379> rpush names Jake
(integer) 4
127.0.0.1:6379> lrange names 0 -1
1) "Lucy"
2) "Andy"
3) "Rose"
4) "Jake"
127.0.0.1:6379> lpop names
"Lucy"
127.0.0.1:6379> rpop names
"Jake"
127.0.0.1:6379> lrange names 0 -1
1) "Andy"
2) "Rose"
127.0.0.1:6379>
操作集合Set
命令:
- 添加:sadd key value
- 獲?。?strong>smembers key,獲取set集合中所有元素
- 刪除:srem key value,刪除set集合中的某個元素
代碼:
127.0.0.1:6379> sadd nums 1
(integer) 1
127.0.0.1:6379> sadd nums 2
(integer) 1
127.0.0.1:6379> sadd nums 3
(integer) 1
127.0.0.1:6379> sadd nums 11
(integer) 1
127.0.0.1:6379> smembers nums
1) "1"
2) "2"
3) "3"
4) "11"
127.0.0.1:6379> srem nums 11
(integer) 1
127.0.0.1:6379> smembers nums
1) "1"
2) "2"
3) "3"
127.0.0.1:6379>
操作有序集合sorted set
命令:
- 添加:
zadd key score value - 獲?。?code>zrange key start end [withscores]
- 刪除:
zrem key value
代碼:
127.0.0.1:6379> zadd salarys 1 1000
(integer) 1
127.0.0.1:6379> zadd salarys 2 2000
(integer) 1
127.0.0.1:6379> zadd salarys 3 3000
(integer) 1
127.0.0.1:6379> zrange salarys 0 -1
1) "1000"
2) "2000"
3) "3000"
127.0.0.1:6379> zrem salarys 3000
(integer) 1
127.0.0.1:6379> zrange salarys 0 -1 withscores
1) "1000"
2) "1"
3) "2000"
4) "2"
操作哈希結構
命令:
- 添加:
hset key field value - 獲?。?
-
hget key field: 獲取指定的field對應的值 -
hgetall key:獲取所有的field和value
-
- 刪除:
hdel key field
代碼:
127.0.0.1:6379> hset user name Bruce
(integer) 1
127.0.0.1:6379> hset user age 10
(integer) 1
127.0.0.1:6379> hset user sex man
(integer) 1
127.0.0.1:6379> hget user age
"10"
127.0.0.1:6379> hgetall user
1) "name"
2) "Bruce"
3) "age"
4) "10"
5) "sex"
6) "man"
127.0.0.1:6379> hdel user sex
(integer) 1
127.0.0.1:6379> hgetall user
1) "name"
2) "Bruce"
3) "age"
4) "10"
1.6-Redis通用命令
-
keys *: 查詢所有的鍵 -
type key: 獲取鍵對應的value的類型 -
del key:刪除指定的key value -
flushall:清空整個redis
127.0.0.1:6379> keys *
1) "salarys"
2) "nums"
3) "user"
4) "names"
127.0.0.1:6379> type names
list
127.0.0.1:6379> type user
hash
127.0.0.1:6379> type salarys
zset
127.0.0.1:6379> type nums
set
127.0.0.1:6379> del salarys
(integer) 1
127.0.0.1:6379> keys *
1) "nums"
2) "user"
3) "names"
127.0.0.1:6379>
1.7-Redis持久化
redis是一個內存數(shù)據(jù)庫,當redis服務器重啟,獲取電腦重啟,數(shù)據(jù)會丟失,我們可以將redis內存中的數(shù)據(jù)持久化保存到硬盤的文件中。
方式1: RDB:默認方式,不需要進行配置,默認就使用這種機制
在一定的間隔時間中,檢測key的變化情況,然后持久化數(shù)據(jù)
可以通過修改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服務器,并指定配置文件名稱:redis-server.exe redis.windows.conf
方式2: AOF:日志記錄的方式,可以記錄每一條命令的操作。可以每一次命令操作后,持久化數(shù)據(jù)
編輯redis.windwos.conf文件
# appendonly no(關閉aof) --> appendonly yes (開啟aof)
# appendfsync no不進行持久化
appendonly yes
# appendfsync always : 每一次操作都進行持久化
appendfsync everysec : 每隔一秒進行一次持久化
第二章:Jedis
Jedis: 一款java操作redis數(shù)據(jù)庫的工具
2.1 快速入門
下載jar包
鏈接:https://pan.baidu.com/s/1CoTLQxcpUkb18KaNyS4YuA
提取碼:zzr2
代碼
package cn.redisDemo.test;
import org.junit.Test;
import redis.clients.jedis.Jedis;
public class Test01 {
@Test
public void test01 (){
// 創(chuàng)建jedis對象
Jedis jedis = new Jedis("127.0.0.1",6379);
jedis.set("userName","Tom");
jedis.close();
}
}
2.2-Jedis操作redis
使用步驟
- 創(chuàng)建Jedis對象:
Jedis jedis = new Jedis(host,port); - 調用方法操作數(shù)據(jù)結構。
- 操作字符串
- 設置:set(key,value);
- 獲?。篻et(key);
- 刪除:del(key);
- 操作列表
- lpush(key,...value);
- rpush(key,...value);
- lpop(key,value);
- rpop(key,value);
- lrange(key,start,end);
- 操作hash
- hset(key,field,value);
- hdel(key,field);
- hget(key,field);
- hgetAll(key);
- 操作set
- sadd(key,..value);
- srem(key,value);
- smembers(key);
- 操作sorted set
- zadd(key,score,value);
- zrem(key,value);
- zrange(key,start,end);
- 操作字符串
- 關閉連接
代碼
package cn.redisDemo.test;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Test01 {
@Test
public void test01 (){
// 創(chuàng)建jedis對象
Jedis jedis = new Jedis("127.0.0.1",6379);
// 【操作字符串】
jedis.set("userName","Tom");
System.out.println(jedis.get("userName")); // Tom
jedis.del("userName");
System.out.println(jedis.get("userName")); // null
// 【操作列表List】
jedis.lpush("names","張三","李四");
jedis.rpush("names","朵朵","海棠");
List<String> list = jedis.lrange("names", 0, -1);
System.out.println(list); // [李四, 張三, 朵朵, 海棠]
jedis.lpop("names");
jedis.rpop("names");
list = jedis.lrange("names", 0, -1);
System.out.println(list); // [張三, 朵朵]
// 【操作set】
jedis.sadd("nums","1000","2000","3000");
Set<String> nums = jedis.smembers("nums");
System.out.println(nums); // [1000, 2000, 3000]
jedis.srem("nums","3000");
nums = jedis.smembers("nums");
System.out.println(nums); // [1000, 2000]
// 【操作sorted set】
jedis.zadd("id",1,"110");
jedis.zadd("id",2,"120");
jedis.zadd("id",3,"114");
Set<String> ids = jedis.zrange("id", 0, -1);
System.out.println(ids); // [110, 120, 114]
jedis.zrem("id","110");
ids = jedis.zrange("id", 0, -1);
System.out.println(ids); // [120, 114]
// 【操作hash】
jedis.hset("users","1","{\"name\":\"Bruce\",\"age\":10}");
jedis.hset("users","2","{\"name\":\"Andy\",\"age\":10}");
jedis.hset("users","3","{\"name\":\"Jake\",\"age\":10}");
Map<String, String> users = jedis.hgetAll("users");
System.out.println(users); // {1={"name":"Bruce","age":10}, 2={"name":"Andy","age":10}, 3={"name":"Jake","age":10}}
jedis.hdel("users","1");
users = jedis.hgetAll("users");
System.out.println(users); // {2={"name":"Andy","age":10}, 3={"name":"Jake","age":10}}
jedis.close();
}
}
2.3-Jedis連接池
JedisPool
package cn.redisDemo.test;
import org.junit.Test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class Test02 {
JedisPool pool = new JedisPool("127.0.0.1",6379);
@Test
public void test01(){
// 從連接池中獲取Jedis對象
Jedis jedis = pool.getResource();
// 使用
jedis.set("name","Bruce");
System.out.println(jedis.get("name"));
// 歸還到連接池
jedis.close();
}
}
Jedis連接池工具類
配置文件:jedis配置文件
host=127.0.0.1
port=6379
maxTotal=50
maxIdle=10
更多配置:
#最大活動對象數(shù)
redis.pool.maxTotal=1000
#最大能夠保持idel狀態(tài)的對象數(shù)
redis.pool.maxIdle=100
#最小能夠保持idel狀態(tài)的對象數(shù)
redis.pool.minIdle=50
#當池內沒有返回對象時,最大等待時間
redis.pool.maxWaitMillis=10000
#當調用borrow Object方法時,是否進行有效性檢查
redis.pool.testOnBorrow=true
#當調用return Object方法時,是否進行有效性檢查
redis.pool.testOnReturn=true
#“空閑鏈接”檢測線程,檢測的周期,毫秒數(shù)。如果為負值,表示不運行“檢測線程”。默認為-1.
redis.pool.timeBetweenEvictionRunsMillis=30000
#向調用者輸出“鏈接”對象時,是否檢測它的空閑超時;
redis.pool.testWhileIdle=true
# 對于“空閑鏈接”檢測線程而言,每次檢測的鏈接資源的個數(shù)。默認為3.
redis.pool.numTestsPerEvictionRun=50
#redis服務器的IP
redis.ip=xxxxxx
#redis服務器的Port
redis1.port=6379
工具類代碼:
package cn.redisDemo.test;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class JedisUtil {
private static JedisPool pool = null;
static {
InputStream resourceAsStream = JedisUtil.class.getClassLoader().getResourceAsStream("jedis.properties");
Properties pro = new Properties();
try {
pro.load(resourceAsStream);
} catch (IOException e) {
e.printStackTrace();
}
// 設置JedisPoolConfig
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));
config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle")));
// 創(chuàng)建連接池對象
pool = new JedisPool(config,pro.getProperty("host"),Integer.parseInt(pro.getProperty("port")));
}
// 獲取Jedis連接對象
public static Jedis getJedis(){
return pool.getResource();
}
}
測試類
package cn.redisDemo.test;
import org.junit.Test;
import redis.clients.jedis.Jedis;
public class Test02 {
@Test
public void test01(){
Jedis jedis = JedisUtil.getJedis();
String name = jedis.get("name");
System.out.println(name);
jedis.close();
}
}