❶ spring boot集成redis為什麼報數據源裝載失敗
在使用spring boot做負載均衡的時候,多個app之間的session要保持一致,這樣負載到不同的app時候,在一個app登錄之後,而打到另外一台伺服器的時候,session丟失。
常規的解決方案都是使用:如apache使用mod_jk.conf。
在開發spring boot app的時候可以藉助 spring session 和redis,用外置的redis來存儲session的狀態。
直接上代碼,我這邊直接默認你使用spring boot,如果你是普通的spring web項目,請參照 https://github.com/spring-projects/spring-session ,在spring boot配置更簡單
1、增加repository到pom.xml
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
2、增加相關依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
<version>1.0.0.RC1</version>
<type>pom</type>
</dependency>
3、RedisSessionConfig.java
package com.wisely.base;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@Configuration
@EnableRedisHttpSession
public class RedisSessionConfig {
}
4、相關配置修改
在application.properties修改redis配置信息(請自行安裝redis),請根據實際修改。如:
spring.redis.host=192.168.1.103
5、所有實體類實現Serializable介面
public class SysResource implements Serializable
6、查看效果
這時候登錄系統在不同的app之間跳轉的時候,session都是一致了,redis上可以看到:
7、總結
使用這些代碼之後 ,無論你使用nginx或者apache,都無須在關心多個app之間的session一致的問題了。
❷ redis怎麼會崩潰
由於redis存儲在內存中且提供一般編程語言常用的數據結構存儲類型,所以經常被用於做伺服器崩潰宕機的數據恢復處理。
伺服器可以在某些指定過程中將需要保存的數據以json對象等方式存儲到redis中,也就是我們常說的快照,當伺服器運行時讀取redis來判斷是否有待需要恢復數據繼續處理的業務。
當一次業務處理結束後再刪除redis的數據即可。
redis提供兩種將內存數據導出到硬碟實現數據備份的方法:
RDB方式(默認)
RDB方式的持久化是通過快照(snapshotting)完成的,當符合一定條件時Redis會自動將內存中的所有數據進行快照並存儲在硬碟上。進行快照的條件可以由用戶在配置文件中自定義,由兩個參數構成:時間和改動的鍵的個數。當在指定的時間內被更改的鍵的個數大於指定的數值時就會進行快照。RDB是redis默認採用的持久化方式,在配置文件中已經預置了3個條件:
save 900 1 # 900秒內有至少1個鍵被更改則進行快照
save 300 10 # 300秒內有至少10個鍵被更改則進行快照
save 60 10000 # 60秒內有至少10000個鍵被更改則進行快照
可以存在多個條件,條件之間是「或」的關系,只要滿足其中一個條件,就會進行快照。 如果想要禁用自動快照,只需要將所有的save參數刪除即可。
Redis默認會將快照文件存儲在當前目錄(可CONFIG GET dir來查看)的mp.rdb文件中,可以通過配置dir和dbfilename兩個參數分別指定快照文件的存儲路徑和文件名。
Redis實現快照的過程
Redis使用fork函數復制一份當前進程(父進程)的副本(子進程);
父進程繼續接收並處理客戶端發來的命令,而子進程開始將內存中的數據寫入硬碟中的臨時文件;
當子進程寫入完所有數據後會用該臨時文件替換舊的RDB文件,至此一次快照操作完成。
在執行fork的時候操作系統(類Unix操作系統)會使用寫時復制(-on-write)策略,即fork函數發生的一刻父子進程共享同一內存數據,當父進程要更改其中某片數據時(如執行一個寫命令 ),操作系統會將該片數據復制一份以保證子進程的數據不受影響,所以新的RDB文件存儲的是執行fork一刻的內存數據。
Redis在進行快照的過程中不會修改RDB文件,只有快照結束後才會將舊的文件替換成新的,也就是說任何時候RDB文件都是完整的。這使得我們可以通過定時備份RDB文件來實 現Redis資料庫備份。RDB文件是經過壓縮(可以配置rdbcompression參數以禁用壓縮節省CPU佔用)的二進制格式,所以佔用的空間會小於內存中的數據大小,更加利於傳輸。
除了自動快照,還可以手動發送SAVE或BGSAVE命令讓Redis執行快照,兩個命令的區別在於,前者是由主進程進行快照操作,會阻塞住其他請求,後者會通過fork子進程進行快照操作。 Redis啟動後會讀取RDB快照文件,將數據從硬碟載入到內存。根據數據量大小與結構和伺服器性能不同,這個時間也不同。通常將一個記錄一千萬個字元串類型鍵、大小為1GB的快照文件載入到內 存中需要花費20~30秒鍾。 通過RDB方式實現持久化,一旦Redis異常退出,就會丟失最後一次快照以後更改的所有數據。這就需要開發者根據具體的應用場合,通過組合設置自動快照條件的方式來將可能發生的數據損失控制在能夠接受的范圍。如果數據很重要以至於無法承受任何損失,則可以考慮使用AOF方式進行持久化。
AOF方式
默認情況下Redis沒有開啟AOF(append only file)方式的持久化,可以在redis.conf中通過appendonly參數開啟:
appendonly yes
在啟動時Redis會逐個執行AOF文件中的命令來將硬碟中的數據載入到內存中,載入的速度相較RDB會慢一些
開啟AOF持久化後每執行一條會更改Redis中的數據的命令,Redis就會將該命令寫入硬碟中的AOF文件。AOF文件的保存位置和RDB文件的位置相同,都是通過dir參數設置的,默認的文件名是appendonly.aof,可以通過appendfilename參數修改:
appendfilename appendonly.aof
配置redis自動重寫AOF文件的條件
auto-aof-rewrite-percentage 100 # 當目前的AOF文件大小超過上一次重寫時的AOF文件大小的百分之多少時會再次進行重寫,如果之前沒有重寫過,則以啟動時的AOF文件大小為依據
auto-aof-rewrite-min-size 64mb # 允許重寫的最小AOF文件大小
配置寫入AOF文件後,要求系統刷新硬碟緩存的機制
# appendfsync always # 每次執行寫入都會執行同步,最安全也最慢
appendfsync everysec # 每秒執行一次同步操作
# appendfsync no # 不主動進行同步操作,而是完全交由操作系統來做(即每30秒一次),最快也最不安全
Redis允許同時開啟AOF和RDB,既保證了數據安全又使得進行備份等操作十分容易。此時重新啟動Redis後Redis會使用AOF文件來恢復數據,因為AOF方式的持久化可能丟失的數據更少
我們簡單做一個定時計數器的小程序
[javascript]view plain
redis=require('redis'),//導入js模塊
RDS_PORT=1379,//埠號
RDS_HOST='47.93.112.119',//伺服器IP
RDS_OPTS={},//設置項
redisdb=redis.createClient(RDS_PORT,RDS_HOST,RDS_OPTS);//創建連接
redisdb.select(20);//指定分區庫
redisdb.on('ready',function(res){
console.log('ready');
});
redisdb.on('connect',function(){
console.log('connect');
});
exports.redisdb=redisdb;
functionredis_opt(opt,key,value,callback){
if(opt=='get'){
redisdb.get(key,function(err,data){
if(err==null){
callback(data);
}
else{
callback(err);
}
});
}
elseif(opt=='set')
{
redisdb.set(key,value,function(err,result){
if(err==null){
callback(result);
}
else{
callback(err);
}
});
}
elseif(opt=='del')
{
redisdb.del(key,function(err,result){
if(err==null){
callback(result);
}
else{
callback(err);
}
});
}
else
{
callback("erroropt!");
}
}
functionupdate(key)
{
redis_opt("get",key,null,function(data){
console.log("theredisdatais"+data);
if(data){
count=parseInt(data);
redis_opt("set",key,++count,function(data){
console.log("set"+count+""+data);
});
}
else{
redis_opt("set",key,10000,function(data){
console.log("set"+10000+""+data);
});
}
});
}
functionclear(key)
{
redis_opt("del",key,null,function(ret){
console.log("del"+key+""+ret);
});
}
functionmain()
{
varkey="count_test";
setInterval(function(){clear(key)},5000);
setInterval(function(){update(key)},1000);
}
//testmain();
main();
以上代碼為簡單的計時器函數,即伺服器啟動後定時讀取redis的數據,如果存在則累加修改,不存在則初始化,同時為了方便說明,又設置了一個定時刪除數據的定時器。
❸ redis存儲session 為什麼存不進去
最近在用redis存session
根據網上例子做了如下配置
'redis' => require(__DIR__ . '/redis.php'),
'session' => [
'class' => 'yii\redis\Session',
'keyPrefix'=>'test',
'redis'=>'redis'
],
現在是訪問介面是可以生成一個根據session_id生成的key在redis裡面 。
但當我
$session = Yii::$app->session;
$session->set('id','s');
卻怎麼也插不進去。。求教大神為什麼,。。。。
跟你的這個插件有很大的關系,你這個class 看看源碼最好
❹ redis怎麼存儲
redis是一個性能非常優秀的內存資料庫,通過key-value存儲系統。
和Memcached類似,它支持存儲的value類型相對更多,包括string(字元串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hashs(哈希類型)。
這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。
與memcached一樣,為了保證效率,數據都是緩存在內存中。區別的是redis會周期性的把更新的數據寫入磁碟或者把修改操作寫入追加的記錄文件,並且在此基礎上實現了master-slave(主從)同步。
❺ redis 報錯 ConfigurationChanged
系統出問題了。
一般情況下,報錯這種錯誤率是極低的,這種信息量的東西,一般都是要求非常嚴格的,如果有報錯,多半都是系統的問題,檢查一下系統是否有病毒侵入。
Redis是一個使用ANSIC編寫的開源支持網路、基於內存、可選持久性的高性能鍵值對存儲資料庫。Redis是一個高性能的keyvalue資料庫。redis的出現,很大程度補償了memcached這類keyvalue存儲的不足,在部分場合可以對關系資料庫起到很好的補充作用。
❻ redis處理數據問題
我印象中Redis的眾多數據類型中,並沒有隊列(Queue)的數據類型,Redis的數據類型有:string(字元串),Hash(哈希),List(列表),Set(集合),有序集合(Sorted Set)。
如果你僅僅想生成訂單號(OrderSn),可以提前生成好Sn號並入隊,然後存儲在Redis緩存里。
例如:
//偽代碼
Queue<string>snQueue=null;//訂單號Sn隊列
stringsn=Redis.Get("OrderSn");
stringcurSn=string.Empty;
if(String.IsNullOrWhiteSpace(sn)){
snQueue=newQueue<string>();
for(inti=0;i<30000;i++)//假定雙11,每秒3萬訂單
{
//提前分配好訂單Sn號入隊
snQueue.Enqueue(DateTime.Now.ToString("yyyMMdd")+i);
}
curSn=snQueue.Dequeue();//出隊
Redis.Set("OrderSn",JsonConvert.SerializeObject(snQueue));
}
else
{
snQueue=JsonConvert.DeserializeObject<Queue<string>>(sn);
curSn=snQueue.Dequeue();//出隊
Redis.Set("OrderSn",JsonConvert.SerializeObject(snQueue));//重新放入Redis緩存
}