springboot整合Redis、mongodb
阿新 • • 發佈:2019-01-11
springboot整合Redis、mongodb
一. springboot整合Redis
1.1 Nosql回顧
NoSQL,泛指非關係型的資料庫,NoSQL即Not-Only SQL,它可以作為關係型資料庫的良好補充。隨著網際網路web2.0網站的興起,非關係型的資料庫現在成了一個極其熱門的新領域,非關係資料庫產品的發展非常迅速
而傳統的關係資料庫在應付web2.0網站,特別是超大規模和高併發的SNS型別的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資料庫的產生就是為了解決大規模資料集合多重資料種類帶來的挑戰,尤其是大資料應用難題
1.2 NoSQL的類別
1.2.1鍵值(Key-Value)儲存資料庫
相關產品: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
典型應用: 內容快取,主要用於處理大量資料的高訪問負載。
資料模型: 一系列鍵值對
優勢: 快速查詢
劣勢: 儲存的資料缺少結構化
1.2.2 列儲存資料庫
相關產品:Cassandra, HBase, Riak 典型應用:分散式的檔案系統 資料模型:以列簇式儲存,將同一列資料存在一起 優勢:查詢速度快,可擴充套件性強,更容易進行分散式擴充套件 劣勢:功能相對侷限
1.2.3 文件型資料庫
相關產品:CouchDB、MongoDB
典型應用:Web應用(與Key-Value類似,Value是結構化的)
資料模型: 一系列鍵值對
優勢:資料結構要求不嚴格
劣勢: 查詢效能不高,而且缺乏統一的查詢語法
1.2.4 圖形(Graph)資料庫
相關資料庫:Neo4J、InfoGrid、Infinite Graph
典型應用:社交網路
資料模型:圖結構
優勢:利用圖結構相關演算法。
劣勢:需要對整個圖做計算才能得出結果,不容易做分散式的叢集方案。
1.3 Redis簡介
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支援的鍵值資料型別如下:
字串型別
雜湊型別
列表型別
集合型別
有序集合型別
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等多種語言。
1.4 Redis的應用場景
目前全球最大的Redis使用者是新浪微博,在新浪有200多臺物理機,400多個埠正在執行Redis,有+4G的資料在Redis上來為微博使用者提供服務
- 取最新的N個數據(取最新文件、排行榜等)
- 需要精確設定過期時間的應用
- 計數器應用
- 實時性要求的高併發讀寫
- 訊息系統Pub/Sub
- 構建佇列
- 快取
1.5 Redis優缺點
1.5.1 Redis 優勢
對資料高併發讀寫(基於記憶體)
對海量資料的高效率儲存和訪問(基於記憶體)
對資料的可擴充套件性和高可用性
垂直擴充套件:提升硬體
水平擴充套件:叢集
1.5.2 Redis 缺點
redis(ACID處理非常簡單)無法做到太複雜的關係資料庫模型
1.6 Redis面向網際網路的解決方案
- 主從:一主多從,主機可寫,從機備份。類似於Mysql的讀寫分離,存在問題是一但主節點down掉,整個Redis不可用。
- 哨兵(2.x):啟用一個哨兵程式(節點),監控其餘節點的狀態,根據選舉策略,進行主從切換。
缺點:每個節點的資料依舊是一致的,仍無法實現分散式的資料庫。
- 叢集(3.x):結合上述兩種模式,多主多從,實現高可用、分散式資料儲存
1.7 springboot整合redis
簡單使用快取的方式:
第一步:匯入包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
第二步:在application.properties
中的配置
# 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, String> redisTemplate(RedisConnectionFactory 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;
}
}
第四步:測試程式碼的編寫:
@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);
}
}
二. springboot整合mongoDB
2.1 mongoDB簡介
MongoDB 是由C++語言編寫的,是一個基於分散式檔案儲存的開源資料庫系統。
在高負載的情況下,新增更多的節點,可以保證伺服器效能。
MongoDB 旨在為WEB應用提供可擴充套件的高效能資料儲存解決方案。
MongoDB 將資料儲存為一個文件,資料結構由鍵值(key=>value)對組成。MongoDB 文件類似於 JSON 物件。欄位值可以包含其他文件,陣列及文件陣列。
特點:
- MongoDB 是一個面向文件儲存的資料庫,操作起來比較簡單和容易。
- 你可以在MongoDB記錄中設定任何屬性的索引 (如:FirstName=“Sameer”,Address=“8 Gandhi Road”)來實現更快的排序。
- 你可以通過本地或者網路建立資料映象,這使得MongoDB有更強的擴充套件性。
- 如果負載的增加(需要更多的儲存空間和更強的處理能力) ,它可以分佈在計算機網路中的其他節點上這就是所謂的分片。
- 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) | 比較說明 |
---|---|---|---|
實現語言 | c++ | c/c++ | - |
協議 | BSON,自定義二進位制 | 類telnet | - |
效能 | 依賴記憶體,TPS較高 | 依賴記憶體,TPS非常高 | Redis優於MongoDB |
可操作性 | 豐富的資料表達,索引;最類似於關係型資料庫,支援豐富的查詢語句 | 資料豐富,較少的IO | MongoDB優於Redis |
記憶體及儲存 | 適合大資料量儲存,依賴系統虛擬記憶體,採用映象檔案儲存;記憶體佔用率比較高,官方建議獨立部署在64位系統 | Redis2.0後支援虛擬記憶體特性(VM) 突破實體記憶體限制;資料可以設定時效性,類似於memcache | 不同的應用場景,各有千秋 |
可用性 | 支援master-slave,replicatset(內部採用paxos選舉演算法,自動故障恢復),auto sharding機制,對客戶端遮蔽了故障轉移和切片機制 | 依賴客戶端來實現分散式讀寫;主從複製時,每次從節點重新連線主節點都要依賴整個快照,無增量複製;不支援auto sharding,需要依賴程式設定一致性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
// 刪除集合
db.collection.drop()
// 插入資料
db.COLLECTION_NAME.insert(document)
// 更新資料
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
// 例如:db.test.update({'title':'MongoDB測試'},{$set:{'title':'Test'}},{multi:true})
// 刪除資料
db.collection.remove(
<query>,
{
justOne: <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})
2.4 springboot整合mongoDB
第一步:配置
spring.data.mongodb.uri=mongodb://localhost:27017/student
#spring.data.mongodb.uri=mongodb://name:[email protected]:27017/test,其中name是使用者名稱,pass是密碼
#如果要配置多個數據庫,則中間用","分割,例如spring.data.mongodb.uri=mongodb://192.168.1.1:20000,192.168.1.2:20000,192.168.252.12:20000/test
第二步:程式碼編寫
@Repository
public class StudentDAO {
@Resource
private MongoTemplate mongoTemplate;
/**
* 新增
*/
public void save(Student student){
mongoTemplate.save(student);
}
/**
* 查詢所有
*/
public List<Student> findAll(){
return mongoTemplate.findAll(Student.class);
}
/**
* 查詢ID
*/
public Student findById(String id){
return mongoTemplate.findById(id, Student.class);
}
/**
* 條件查詢
*/
public List<Student> findByName(String name){
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);
}
}