springboot整合Redis、mongodb


一. springboot整合Redis

1.1 Nosql回顧

而傳統的關係數據庫在應付web2.0網站,特別是超大規模和高併發的SNS類型的web2.0純動態網站已經顯得力不從心,暴露了很多難以克服的問題,例如:

p1

1.2 NoSQL的類別

1.2.1鍵值(Key-Value)存儲數據庫

1.2.2 列存儲數據庫

NoSQL,泛指非關係型的數據庫,NoSQL即Not-Only SQL,它可以作為關係型數據庫的良好補充。隨著互聯

網web2.0網站的興起,非關係型的數據庫現在成了一個極其熱門的新領域,非關係數據庫產品的發展非常迅

1、High performance - 對數據庫高併發讀寫的需求

web2.0網站要根據用戶個性化信息來實時生成動態頁面和提供動態信息,所以基本上無法使用動態頁面靜態

化技術,因此數據庫併發負載非常高,往往要達到每秒上萬次讀寫請求。關係數據庫應付上萬次SQL查詢還勉

強頂得住,但是應付上萬次SQL寫數據請求,硬盤IO就已經無法承受了。其實對於普通的BBS網站,往往也存

在對高併發寫請求的需求,例如網站的實時統計在線用戶狀態,記錄熱門帖子的點擊次數,投票計數等,因此

這是一個相當普遍的需求。

2、Huge Storage - 對海量數據的高效率存儲和訪問的需求

類似Facebook,twitter,Friendfeed這樣的SNS網站,每天用戶產生海量的用戶動態,以Friendfeed

為例,一個月就達到了2.5億條用戶動態,對於關係數據庫來說,在一張2.5億條記錄的表裡面進行SQL查詢,

效率是極其低下乃至不可忍受的。再例如大型web網站的用戶登錄系統,例如騰訊,盛大,動輒數以億計的帳

號,關係數據庫也很難應付。

3、High Scalability && High Availability- 對數據庫的高可擴展性和高可用性的需求

在基於web的架構當中,數據庫是最難進行橫向擴展的,當一個應用系統的用戶量和訪問量與日俱增的時候,

你的數據庫卻沒有辦法像web server和app server那樣簡單的通過添加更多的硬件和服務節點來擴展性能

和負載能力。對於很多需要提供24小時不間斷服務的網站來說,對數據庫系統進行升級和擴展是非常痛苦的事

情,往往需要停機維護和數據遷移,為什麼數據庫不能通過不斷的添加服務器節點來實現擴展呢?

NoSQL數據庫的產生就是為了解決大規模數據集合多重數據種類帶來的挑戰,尤其是大數據應用難題

相關產品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB

典型應用: 內容緩存,主要用於處理大量數據的高訪問負載。

數據模型: 一系列鍵值對

優勢: 快速查詢

劣勢: 存儲的數據缺少結構化


1.2.3 文檔型數據庫

1.2.4 圖形(Graph)數據庫

1.3 Redis簡介

相關產品:Cassandra, HBase, Riak

典型應用:分佈式的文件系統

數據模型:以列簇式存儲,將同一列數據存在一起

優勢:查找速度快,可擴展性強,更容易進行分佈式擴展

劣勢:功能相對侷限

相關產品:CouchDB、MongoDB

典型應用:Web應用(與Key-Value類似,Value是結構化的)

數據模型: 一系列鍵值對

優勢:數據結構要求不嚴格

劣勢: 查詢性能不高,而且缺乏統一的查詢語法

相關數據庫:Neo4J、InfoGrid、Infinite Graph

典型應用:社交網絡

數據模型:圖結構

優勢:利用圖結構相關算法。

劣勢:需要對整個圖做計算才能得出結果,不容易做分佈式的集群方案。

2008年,意大利的一家創業公司Merzia推出了一款基於MySQL的網站實時統計系統LLOOGG,然而沒過多久

該公司的創始人 Salvatore Sanfilippo便對MySQL的性能感到失望,於是他決定親自為LLOOGG量身定做

一個數據庫,並於2009年開發完成,這個數據庫就是Redis。不過Salvatore Sanfilippo並不滿足只將

Redis用於LLOOGG這一款產品,而是希望更多的人使用它,於是在同一年Salvatore Sanfilippo將

Redis開源發佈,並開始和Redis的另一名主要的代碼貢獻者Pieter Noordhuis一起繼續著Redis的開

發,直到今天。

Salvatore Sanfilippo自己也沒有想到,短短的幾年時間,Redis就擁有了龐大的用戶群體。Hacker

News在2012年發佈了一份數據庫的使用情況調查,結果顯示有近12%的公司在使用Redis。國內如新浪微

博、街旁網、知乎網,國外如GitHub、Stack Overflow、Flickr等都是Redis的用戶。

VMware公司從2010年開始贊助Redis的開發, Salvatore Sanfilippo和Pieter Noordhuis也分別在

3月和5月加入VMware,全職開發Redis。

Redis是用C語言開發的一個開源的高性能鍵值對(key-value)數據庫。它通過提供多種鍵值數據類型來適

應不同場景下的存儲需求,目前為止Redis支持的鍵值數據類型如下:

字符串類型

散列類型

列表類型

集合類型

有序集合類型


1.4 Redis的應用場景

1.5 Redis優缺點

1.5.1 Redis 優勢

1.5.2 Redis 缺點

1.6 Redis面向互聯網的解決方案

1.7 springboot整合redis

簡單使用緩存的方式:

第一步:導入包

Redis 與其他 key - value 緩存產品有以下三個特點:

- Redis支持數據的持久化,可以將內存中的數據保存在磁盤中,重啟的時候可以再次加載進行使用。

- Redis不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存

儲。

- Redis支持數據的備份,即master-slave模式的數據備份。

Redis 提供的API支持:C、C++、C#、Clojure、Java、JavaScript、Lua、PHP、Python、

Ruby、Go、Scala、Perl等多種語言。

目前全球最大的Redis用戶是新浪微博,在新浪有200多臺物理機,400多個端口正在運行Redis,有+4G的數

據在Redis上來為微博用戶提供服務

- 取最新的N個數據(取最新文檔、排行榜等)

- 需要精確設定過期時間的應用

- 計數器應用

- 實時性要求的高併發讀寫

- 消息系統Pub/Sub

- 構建隊列

- 緩存

對數據高併發讀寫(基於內存)

對海量數據的高效率存儲和訪問(基於內存)

對數據的可擴展性和高可用性

垂直擴展:提升硬件

水平擴展:集群

redis(ACID處理非常簡單)無法做到太複雜的關係數據庫模型

- 主從:一主多從,主機可寫,從機備份。類似於Mysql的讀寫分離,存在問題是一但主節點down掉,整個

Redis不可用。

- 哨兵(2.x):啟用一個哨兵程序(節點),監控其餘節點的狀態,根據選舉策略,進行主從切換。

缺點:每個節點的數據依舊是一致的,仍無法實現分佈式的數據庫。

- 集群(3.x):結合上述兩種模式,多主多從,實現高可用、分佈式數據存儲


第二步:在 application.properties 中的配置

第三步:配置代碼的編寫

<dependency>

<groupid>org.springframework.boot/<groupid>

<artifactid>spring-boot-starter-data-redis/<artifactid>

# Redis數據庫索引(默認為0)

spring.redis.database=0

# Redis服務器地址

spring.redis.host=127.0.0.1

# Redis服務器連接端口

spring.redis.port=6379

# 連接池最大連接數(使用負值表示沒有限制)

spring.redis.pool.max-active=8

# 連接池最大阻塞等待時間(使用負值表示沒有限制)

spring.redis.pool.max-wait=-1

# 連接池中的最大空閒連接

spring.redis.pool.max-idle=8

# 連接池中的最小空閒連接

spring.redis.pool.min-idle=0

# 連接超時時間(毫秒)

spring.redis.timeout=0

@Configuration

@EnableCaching

public class CacheConfig extends CachingConfigurerSupport {

@Bean

public CacheManager cacheManager(RedisTemplate redisTemplate) {

RedisCacheManager rcm = new RedisCacheManager(redisTemplate);

// 多個緩存的名稱,目前只定義了一個

rcm.setCacheNames(Arrays.asList("thisredis"));

//設置緩存過期時間(秒)

rcm.setDefaultExpiration(600);

return rcm;

}

@Bean

public RedisTemplate<string> redisTemplate(RedisConnectionFactory/<string>

factory) {

StringRedisTemplate template = new StringRedisTemplate(factory);

Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new

Jackson2JsonRedisSerializer(Object.class);

ObjectMapper om = new ObjectMapper();

om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);

om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);

jackson2JsonRedisSerializer.setObjectMapper(om);

template.setValueSerializer(jackson2JsonRedisSerializer);

template.afterPropertiesSet();

return template;


第四步:測試代碼的編寫:

二. springboot整合mongoDB

2.1 mongoDB簡介

MongoDB 是由C++語言編寫的,是一個基於分佈式文件存儲的開源數據庫系統。

在高負載的情況下,添加更多的節點,可以保證服務器性能。

MongoDB 旨在為WEB應用提供可擴展的高性能數據存儲解決方案。

MongoDB 將數據存儲為一個文檔,數據結構由鍵值(key=>value)對組成。MongoDB 文檔類似於 JSON 對象。字段值可以包含其他文檔,數組及文檔數組。

特點:

MongoDB 是一個面向文檔存儲的數據庫,操作起來比較簡單和容易。你可以在MongoDB記錄中設置任何屬性的索引 (如:FirstName="Sameer",Address="8 Gandhi Road")來實現更快的排序。你可以通過本地或者網絡創建數據鏡像,這使得MongoDB有更強的擴展性。

}

}

@Service

public class UserService {

@Cacheable(value = "thisredis", key = "'users_'+#id")

public Users findUser(Integer id){

Users users = new Users();

users.setUsername("zhangsan");

users.setPassword("123456");

users.setId(id);

System.out.println("測試是否使用緩存");

return users;

}

@CacheEvict(value="thisredis", key="'users_'+#id",condition="#id!=1")

public void deleteUser(Integer id){

System.out.println("刪除user==id:" + id);

}

}

@RunWith(SpringRunner.class)

@SpringBootTest

public class DemoApplicationTests {

@Resource

private UserService userService;

@Test

public void contextLoads() {

// 查看

System.out.println(userService.findUser(2));

// 刪除

// userService.deleteUser(2);

}

}


比較指標

MongoDB(v2.4.9) Redis(v2.4.17) 比較說明

實現語言

c++ c/c++ -

協議

BSON,自定義二進制

類telnet -

性能

依賴內存,TPS較高 依賴內存,TPS非常高 Redis優於MongoDB

可操作性

豐富的數據表達,索引;最類似於關係型數據庫,支持豐富的查詢語句

數據豐富,較少的IO MongoDB優於Redis

如果負載的增加(需要更多的存儲空間和更強的處理能力) ,它可以分佈在計算機網絡中的其他節點上這就是所謂的分片。Mongo支持豐富的查詢表達式。查詢指令使用JSON形式的標記,可輕易查詢文檔中內嵌的對象及數組。MongoDb 使用update()命令可以實現替換完成的文檔(數據)或者一些指定的數據字段 。Mongodb中的Map/reduce主要是用來對數據進行批量處理和聚合操作。Map和Reduce。Map函數調用emit(key,value)遍歷集合中所有的記錄,將key與value傳給Reduce函數進行處理。Map函數和Reduce函數是使用Javascript編寫的,並可以通過db.runCommand或mapreduce命令來執行MapReduce操作。GridFS是MongoDB中的一個內置功能,可以用於存放大量小文件。MongoDB允許在服務端執行腳本,可以用Javascript編寫某個函數,直接在服務端執行,也可以把函數的定義存儲在服務端,下次直接調用即可。MongoDB支持各種編程語言:RUBY,PYTHON,JAVA,C++,PHP,C#等多種語言。MongoDB安裝簡單。

#####2.2 mongoDB與Redis的區別

MongoDB和Redis都是NoSQL,採用結構型數據存儲。二者在使用場景中,存在一定的區別,這也主要由於二者在內存映射的處理過程,持久化的處理方法不同。

MongoDB建議集群部署,更多的考慮到集群方案,Redis更偏重於進程順序寫入,雖然支持集群,也僅限於主-從模式。


比較指標

MongoDB(v2.4.9) Redis(v2.4.17) 比較說明

內存及存儲

適合大數據量存儲,依賴系統虛擬內存,採用鏡像文件存儲;內存佔用率比較高,官方建議獨立部署在64位系統

Redis2.0後支持虛擬內存特性(VM) 突破物理內存限制;數據可以設置時效性,類似於memcache

不同的應用場景,各有千秋

可用性

支持master-slave,replicatset(內部採用paxos選舉算法,自動故障恢復),auto sharding機制,對客戶端屏蔽了故障轉移和切片機制

依賴客戶端來實現分佈式讀寫;主從複製時,每次從節點重新連接主節點都要依賴整個快照,無增量複製;不支持autosharding,需要依賴程序設定一致性hash機制

MongoDB優於Redis;單點問題上,MongoDB應用簡單,相對用戶透明,Redis比較複雜,需要客戶端主動解決.(MongoDB一般使用replicasets和sharding相結合,replicasets側重高可用性以及高可靠,sharding側重性能,水平擴展)

可靠性

從1.8版本後,採用binlog方式(類似Mysql) 支持持久化

依賴快照進行持久化;AOF增強可靠性;增強性的同時,影響訪問性能

一致性

不支持事務,靠客戶端保證

支持事務,比較脆,僅能保證事務中的操作按順序執行

Redis優於MongoDB

數據分析

內置數據分析功能(mapreduce)

不支持 MongoDB優於Redis

應用場景

海量數據的訪問效率提升

較小數據量的性能和運算

MongoDB優於Redis

#####2.3 mongoDB基本操作

// 查看所有數據庫

show dbs

// 創建數據庫

use DATABASE_NAME

// 查看當前數據

db

// 刪除當前數據庫(先切換,再刪除)

use DATABASE_NAME

db.dropDatabase()

// 創建集合(也可以直接插入值的時候自動創建)

db.createCollection(name, options)

// 查看集合

show collections

// 刪除集合


2.4 springboot整合mongoDB

第一步:配置

第二步:代碼編寫

db.collection.drop()

// 插入數據

db.COLLECTION_NAME.insert(document)

// 更新數據

db.collection.update(

<query>,/<query>

<update>,/<update>

{

upsert: <boolean>,/<boolean>

multi: <boolean>,/<boolean>

writeConcern: <document>

}

)

// 例如:db.test.update({'title':'MongoDB測試'},{$set:{'title':'Test'}},

{multi:true})

// 刪除數據

db.collection.remove(

<query>,/<query>

{

justOne: <boolean>,/<boolean>

writeConcern: <document>

}

)

// 注意:條件為空意味著全部刪除,例如:db.test.remove({})

// 查詢

db.collection.find(query, projection)

db.collection.findOne(query, projection)

// 例如:db.test.find({"num": {$gt:50}, $or: [{"author": "千鋒"},{"title":

"springboot整合mongoDB"}]}).pretty()

// 分頁

db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)

// 排序

db.COLLECTION_NAME.find().sort({KEY:1}) // db.col.find({},

{"title":1,_id:0}).sort({"num":-1})

spring.data.mongodb.uri=mongodb://localhost:27017/student

#spring.data.mongodb.uri=mongodb://name:pass@localhost:27017/test,其中name是用戶

名,pass是密碼

#如果要配置多個數據庫,則中間用","分割,例如

spring.data.mongodb.uri=mongodb://192.168.1.1:20000,192.168.1.2:20000,192.168.25

2.12:20000/test

@Repository

public class StudentDAO {

@Resource

private MongoTemplate mongoTemplate;

/**

* 添加

*/

public void save(Student student){


mongoTemplate.save(student);

}

/**

* 查詢所有

*/

public List<student> findAll(){/<student>

return mongoTemplate.findAll(Student.class);

}

/**

* 查詢ID

*/

public Student findById(String id){

return mongoTemplate.findById(id, Student.class);

}

/**

* 條件查詢

*/

public List<student> findByName(String name){/<student>

Query query = new Query(Criteria.where("name").is(name));

return mongoTemplate.find(query, Student.class);

}

/**

* 修改

*/

public void update(Student student) {

Query query=new Query(Criteria.where("id").is(student.getId()));

Update update= new Update().set("name", student.getName()).set("sex",

student.getSex());

//更新查詢返回結果集的第一條

mongoTemplate.updateFirst(query,update,Student.class);

//更新查詢返回結果集的所有

// mongoTemplate.updateMulti(query,update,TestEntity.class);

}

/**

* 刪除

*/

public void delete(Integer id) {

Query query=new Query(Criteria.where("id").is(id));

mongoTemplate.remove(query,Student.class);

}

}


分享到:


相關文章: