NoSQL(NoSQL = Not Only SQL),意即「不僅僅是SQL」
是一項全新的數據庫理念,泛指非關係型的數據庫。
web程式不再僅僅專注在功能上,同時也在追求效能
High performance
對數據庫高併發讀寫的需求
現在數據庫併發負載非常高,往往要達到每秒上萬次讀寫請求
關係數據庫應付上萬次SQL查詢還勉強頂得住,但是應付上萬次SQL寫 數據請求,硬碟IO就已經無法承受了
Huge Storage
對海量數據的高效率儲存和存取的需求
對於關係數據庫來說,在一張2.5億條記錄的表裏面進行SQL查詢,效率是極其低下乃至不可忍受的
High Scalability && High Availability-
對數據庫的高可延伸性和高可用性的需求
對於很多需要提供24小時不間斷服務的網站來說,
對數據庫系統進行升級和擴充套件是非常痛苦的事情,往往需要停機維護和數據遷移
主流產品
鍵值(Key-Value)儲存數據庫-redis
主要使用記憶體, 有兩種持久化方案, 速度非常快,
一般做分佈式快取使用
文件型數據庫-MongoDB
主要使用硬碟儲存, 所以不會擔心數據丟失, 速度介於redis和傳統數據庫之間.
但是mongodb更擅長儲存大文字數據, 以及一些非結構化數據,
mongodb比redis的數據型別更加豐富.
例如: 儲存小說網站的小說, 儲存電商網站的評論等這些數據
Redis是用C語言開發的一個開源的高效能鍵值對(key-value)數據庫
官方提供測試數據
50個併發執行100000個請求
讀的速度是110000次/s
寫的速度是81000次/s
快取(數據查詢、短連線、新聞內容、商品內容等等)
聊天室的線上好友列表
任務佇列。(秒殺、搶購、12306等等)
應用排行榜
網站存取統計
數據過期處理(可以精確到毫秒
分佈式叢集架構中的session分離
獲取數據的時候先從redis中獲取, 如果獲取到數據則直接返回, 就不用存取數據庫了
如果獲取不到數據, 可以從數據庫中查詢, 查詢到後放入redis中一份, 下回就可以直接從redis中查詢到
這樣大大降低了數據庫的高併發存取壓力.
RDB(預設) 分時持久化
可以在組態檔中設定, 多長時間持久化一次, 持久化次數少也就是操作硬碟的次數少,
速度快. 但是如果在沒有完成持久化前, 如果伺服器斷電, 則記憶體中沒有持久化的數據會丟失.
AOF 實時持久化
每次向redis中做增刪改操作, 都會將數據持久化到硬碟上, 數據可靠性高, 不會丟失,但是速度慢
鏈接: https://pan.baidu.com/s/1pS_jPx1WenVaO3nwYRdbSQ 提取碼: ac2e
window版的安裝及其簡單,
解壓Redis壓縮包完成即安裝完畢
雙擊Redis目錄中redis-server.exe可以啓動redis服務,Redis服務佔用的埠是6379
關閉Redis的控制檯視窗就可以關閉Redis服務
將redis在Linux的安裝包上傳到/usr/local當中
解壓
tar -xvf redis-4.0.9.tar.gz
編譯安裝
進入到redis目錄
執行命令:
啓動
進入到/usr/local/redis-4.0.9/6379/bin目錄當中
執行命令: ./redis-server
修改組態檔
把/usr/local/redis-4.0.9/目錄下的組態檔複製一份到6379目錄下
命令:cp /usr/local/redis-4.0.9/redis.conf /usr/local/redis-4.0.9/6379/bin/
修改組態檔
vim redis.conf
#bind 127.0.0.1 # 將這行程式碼註釋,監聽所有的ip地址,外網可以存取
protected-mode no # 把yes改成no,允許外網存取
daemonize yes # 把no改成yes,後臺執行
redis是一種高階的key-value的儲存系統,其中value支援五種數據型別
Redis的5種數據型別
1. 字串(String)
2. 雜湊(hash)
3. 字串列表(list)
4. 字串集合(set)
5. 序字串集合(sorted set)
key的定義注意點:
key不要太長,最好不要操作1024個位元組,這不僅會消耗記憶體還會降低查詢效率
key不要太短,如果太短會降低key的可讀性
在專案中,key最好有一個統一的命名規範
在redis-4.0.9/6379/bin目錄下輸入命令
./redis-cli
概述
設定key持有指定的字串value,如果該key存在則進行覆蓋操作。總是返回」OK」
操作
概述
Redis中的Hash型別可以看成具有String Key和String Value的map容器
所以該型別非常適合於儲存值物件的資訊
操作
概述
在Redis中,List型別是按照插入順序排序的字串鏈表。
和數據結構中的普通鏈表一樣,我們可以在其頭部(left)和尾部(right)新增新的元素
在插入時,如果該鍵並不存在,Redis將爲該鍵建立一個新的鏈表
與此相反,如果鏈表中所有的元素均被移除,那麼該鍵也將會被從數據庫中刪除
List中可以包含的最大元素數量是4294967295
操作
lpop key
返回並彈出指定的key關聯的鏈表中的第一個元素,即頭部元素
如果該key不存在,返回nil;若key存在,則返回鏈表的頭部元素。
rpop key
從尾部彈出元素。
lrange key 遍歷該鍵的所有數據
lrange key 0 -1 返回所有
lrange key 0 2 返回從0開始 0 1 2
概述
在Redis中,我們可以將Set型別看作爲沒有排序的字元集合
和List型別一樣,我們也可以在該型別的數據值上執行新增、刪除或判斷某一元素是否存在等操作
Set集閤中不允許出現重複的元素。
操作
在redis中,可以保證不重複的元素,仍然可以進行排序
概述
Redis的高效能是由於其將所有數據都儲存在了記憶體中
爲了使Redis在重新啓動之後仍能保證數據不丟失,需要將數據從記憶體中同步到硬碟中,這一過程就是持久化;Redis支援兩種方式的持久化,可以單獨使用其中一種或將二者結合使用。
一種是RDB方式,一種是AOF方式。
RDB持久化(預設支援,無需設定)
該機制 機製是指在指定的時間間隔內將記憶體中的數據集快照寫入磁碟。
AOF持久化
該機制 機製將以日誌的形式記錄伺服器所處理的每一個寫操作
在Redis伺服器啓動之初會讀取該檔案來重新構建數據庫,以保證啓動後數據庫中的數據是完整的。
無持久化
我們可以通過設定的方式禁用Redis伺服器的持久化功能
這樣我們就可以將Redis視爲一個功能加強版的memcached了
redis可以同時使用RDB和AOF
RDB持久化機制 機製優點
一旦採用該方式,那麼你的整個Redis數據庫將只包含一個檔案
這對於檔案備份而言是非常完美的
RDB持久化機制 機製缺點
如果你想保證數據的高可用性,即最大限度的避免數據丟失,那麼RDB將不是一個很好的選擇。因爲系統一旦在定時持久化之前出現宕機現象,此前沒有來得及寫入磁碟的數據都將丟失。
由於RDB是通過fork子進程來協助完成數據持久化工作的,因此,如果當數據集較大時,可能會導致整個伺服器停止服務幾百毫秒,甚至是1秒鐘
快照觸發條件
用戶端執行命令save和bgsave會生成快照;
根據組態檔save m n規則進行自動快照;
主從複製時,從庫全量複製同步主庫數據,此時主庫會執行bgsave命令進行快照;
用戶端執行數據庫清空命令FLUSHALL時候,觸發快照;
用戶端執行shutdown關閉redis時,觸發快照;
RDB持久化機制 機製的設定
在redis.conf進行修改設定
save m n
設定快照(rdb)促發規則,格式:save
save 900 1 900秒內至少有1個key被改變則做一次快照
save 300 10 300秒內至少有10個key被改變則做一次快照
save 60 10000 60秒內至少有10000個key被改變則做一次快照
#關閉該規則使用save 「 」
dbfilename dump.rdb
rdb持久化儲存數據庫檔名,預設爲dump.rdb
stop-write-on-bgsave-error yes
yes代表當使用bgsave命令持久化出錯時候停止寫RDB快照檔案,no表明忽略錯誤繼續寫檔案。
rdbchecksum yes
在寫入檔案和讀取檔案時是否開啓rdb檔案檢查,檢查是否有無失真壞,如果在啓動是檢查發現損壞,則停止啓動。
dir 「./」
數據檔案存放目錄,rdb快照檔案和aof檔案都會存放至該目錄,請確保有寫許可權
rdbcompression yes
是否開啓RDB檔案壓縮,該功能可以節約磁碟空間
AOF概述
當redis儲存非臨時數據時,爲了降低redis故障而引起的數據丟失,redis提供了AOF(Append Only File)持久化,
從單詞意思講,將命令追加到檔案。AOF可以將Redis執行的每一條寫命令追加到磁碟檔案(appendonly.aof)中
在redis啓動時候優先選擇從AOF檔案恢復數據。由於每一次的寫操作,redis都會記錄到檔案中,所以開啓AOF持久化會對效能有一定的影響
AOF持久化數據丟失更少,其消耗記憶體更少(RDB方式執行bgsve會有記憶體拷貝)
開啓AOF持久化
預設情況下,redis是關閉了AOF持久化,開啓AOF通過設定appendonly爲yes開啓
將appendonly修改爲yes,開啓aof持久化機制 機製,預設會在目錄下產生一個appendonly.aof檔案
我們修改組態檔或者在命令列直接使用config set修改,在用config rewrite同步到組態檔。通過用戶端修改好處是不用重新啓動redis,AOF持久化直接生效
config get appendonly:查詢設定狀態
config set appendonly yes:修改設定
config rewrite:寫入到redis.conf中
設定
appendfsync:always 每執行一次更新命令,持久化一次
appendfsync:everysec 每秒鐘持久化一次
appendfsync:no 不持久化
通過aof-use-rdb-preamble設定參數控制,yes則表示開啓,no表示禁用,預設是禁用的,可通過config set修改。
獲取密碼
config get requirepass
設定密碼
config set requirepass 123456
當有密碼的時候登錄時需要密碼登錄
auth 密碼
取消密碼
config set requirepass ‘’
使用Jedis操作redis需要匯入jar包如下:
jedis常用API
new Jedis(host, port)
建立jedis物件,參數host是redis伺服器地址,參數port是redis伺服器端口
set(key,value)
設定字串型別的數據
get(key)
獲得字串型別的數據
hset(key,field,value)
設定雜湊型別的數據
hget(key,field)
獲得雜湊型別的數據
lpush(key,values)
設定列表型別的數據
lpop(key)
列表左面彈棧
rpop(key)
列表右面彈棧
del(key)
刪除指定的key
jedis的基本操作
public void testJedis(){
//1 設定ip地址和埠
Jedis jedis = new Jedis("localhost", 6379);
//2 設定數據
jedis.set("name", "fmjava");
//3 獲得數據
String name = jedis.get("name");
System.out.println(name);
//4 釋放資源
jedis.close();
}
jedis連線池的基本概念
jedis連線資源的建立與銷燬是很消耗程式效能,所以jedis爲我們提供了jedis的池化技術
範例程式碼
public void testJedisPool(){
//1 獲得連線池設定物件,設定設定項
JedisPoolConfig config = new JedisPoolConfig();
// 1.1 最大連線數
config.setMaxTotal(30);
// 1.2 最大空閒連線數
config.setMaxIdle(10);
//2 獲得連線池
JedisPool jedisPool = new JedisPool(config, "localhost", 6379);
//3 獲得核心物件
Jedis jedis = null;
try {
jedis = jedisPool.getResource();
//4 設定數據
jedis.set("name", "fmjava");
//5 獲得數據
String name = jedis.get("name");
System.out.println(name);
} catch (Exception e) {
e.printStackTrace();
} finally{
if(jedis != null){
jedis.close();
}
// 虛擬機器關閉時,釋放pool資源
if(jedisPool != null){
jedisPool.close();
}
}
}
Spring-data-redis是spring大家族的一部分
提供了在srping應用中通過簡單的設定存取redis服務,對reids底層開發包(Jedis, JRedis, and RJC)進行了高度封裝
RedisTemplate提供了redis各種操作、例外處理及序列化,支援發佈訂閱
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
<!-- 快取 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.2.RELEASE</version>
</dependency>
</dependencies>
redis.host=192.168.0.108
redis.port=6379
redis.pass=
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath*:*.properties" />
<!-- redis 相關設定 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="JedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}"
p:port="${redis.port}"
p:password="${redis.pass}"
p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory" />
</bean>
</beans>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestString {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testSet() {
redisTemplate.boundValueOps("name").set("joker");
}
@Test
public void testGet() {
String name = (String) redisTemplate.boundValueOps("name").get();
System.out.println("name=" + name);
}
@Test
public void testDelete() {
redisTemplate.delete("name");
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestList {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testLpush() {
redisTemplate.boundListOps("myListKey").leftPush("001");
redisTemplate.boundListOps("myListKey").leftPush("002");
redisTemplate.boundListOps("myListKey").leftPush("003");
redisTemplate.boundListOps("myListKey").leftPush("004");
}
@Test
public void testRpush() {
redisTemplate.boundListOps("myListKey").rightPush("001");
redisTemplate.boundListOps("myListKey").rightPush("002");
redisTemplate.boundListOps("myListKey").rightPush("003");
redisTemplate.boundListOps("myListKey").rightPush("004");
}
@Test
public void testRange() {
List<String> myListKey = redisTemplate.boundListOps("myListKey").range(0, -1);
for (String s : myListKey) {
System.out.println("value=" + s);
}
}
@Test
public void testDelete() {
redisTemplate.delete("myListKey");
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestHash {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void testPut() {
redisTemplate.boundHashOps("keyname1").put("name", "zs");
redisTemplate.boundHashOps("keyname1").put("age", "20");
redisTemplate.boundHashOps("keyname1").put("phone", "121");
redisTemplate.boundHashOps("keyname1").put("email", "[email protected]");
}
@Test
public void testGetOne() {
String name = (String)redisTemplate.boundHashOps("keyname1").get("name");
System.out.println("name =" + name);
}
@Test
public void testGetAll() {
//獲取所有的entries
Map<String, String> testHash = (Map<String, String>)redisTemplate.boundHashOps("keyname1").entries();
Set<Map.Entry<String, String>> entries = testHash.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println("key=" + entry.getKey());
System.out.println("value=" + entry.getValue());
}
}
@Test
public void testDeleteOne() {
redisTemplate.boundHashOps("keyname1").delete("name");
}
@Test
public void testDeleteAll() {
redisTemplate.delete("keyname1");
}
}
import java.io.Serializable;
public class Person implements Serializable {
private String name;
private Integer age;
private char sex;
public Person(String name, Integer age, char sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestObject {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void setObject(){
Person person = new Person("joker", 20, '男');
redisTemplate.boundValueOps("person").set(person);
}
@Test
public void getObject(){
Person person=(Person)redisTemplate.boundValueOps("person").get();
}
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.ArrayList;
import java.util.List;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:applicationContext-redis.xml"})
public class TestObject {
@Autowired
private RedisTemplate redisTemplate;
@Test
public void setObject(){
Person person = new Person("joker", 20, '男');
Person person1 = new Person("joker1", 21, '男');
Person person2 = new Person("joker1", 21, '男');
Person person3 = new Person("joker1", 21, '男');
ArrayList<Person> personArrayList=new ArrayList<>();
personArrayList.add(person);
personArrayList.add(person1);
personArrayList.add(person2);
personArrayList.add(person3);
/*分業務*/
redisTemplate.boundHashOps("userService").put("person",personArrayList);
}
@Test
public void getObject(){
List<Person> people=(List<Person>) redisTemplate.boundHashOps("userService").get("person");
System.out.println(people);
}
}
<!-- Jackson Json處理工具包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.4</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
redis.host=192.168.0.108
redis.port=6379
redis.pass=
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true
spring/applicationContext-redis.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="classpath*:/properties/*.properties" />
<!-- redis 相關設定 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="JedisConnectionFactory"
class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}"
p:port="${redis.port}"
p:password="${redis.pass}"
p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory" />
</bean>
</beans>