A. Redis分布式緩存搭建
花了兩天時間整理了之前記錄的Redis單體與哨兵模式的搭建與使用,又補齊了集群模式的使用和搭建經驗,並對集群的一些個原理做了理解。
筆者安裝中遇到的一些問題:
如果make報錯,可能是沒裝gcc或者gcc++編輯器,安裝之 yum -y install gcc gcc-c++ kernel-devel ,有可能還是提示一些個c文件編譯不過,gcc -v查看下版本,如果不到5.3那麼升級一下gcc:
在 /etc/profile 追加一行 source /opt/rh/devtoolset-9/enable
scl enable devtoolset-9 bash
重新make clean, make
這回編譯通過了,提示讓你最好make test一下/
執行make test ,如果提示 You need tcl 8.5 or newer in order to run the Redis test
那就升級tcl, yum install tcl
重新make test,如果還有error就刪了目錄,重新tar包解壓重新make , make test
o/ All tests passed without errors! ,表示編譯成功。
然後make install即可。
直接運行命令: ./redis-server /usr/redis-6.0.3/redis.conf &
redis.conf 配置文件里 bind 0.0.0.0 設置外部訪問, requirepass xxxx 設置密碼。
redis高可用方案有兩種:
常用搭建方案為1主1從或1主2從+3哨兵監控主節點, 以及3主3從6節點集群。
(1)sentinel哨兵
/usr/redis-6.0.3/src/redis-sentinel /usr/redis-6.0.3/sentinel2.conf &
sentinel2.conf配置:
坑1:master節點也會在故障轉移後成為從節點,也需要配置masterauth
當kill master進程之後,經過sentinel選舉,slave成為了新的master,再次啟動原master,提示如下錯誤:
原因是此時的master再次啟動已經是slave了,需要向現在的新master輸入密碼,所以需要在master.conf
中配置:
坑2:哨兵配置文件要暴露客戶端可以訪問到的master地址
在 sentinel.conf 配置文件的 sentinel monitor mymaster 122.xx.xxx.xxx 6379 2 中,配置該哨兵對應的master名字、master地址和埠,以及達到多少個哨兵選舉通過認為master掛掉。其中master地址要站在redis訪問者(也就是客戶端)的角度、配置訪問者能訪問的地址,例如sentinel與master在一台伺服器(122.xx.xxx.xxx)上,那麼相對sentinel其master在本機也就是127.0.0.1上,這樣 sentinel monitor mymaster 127.0.0.1 6379 2 邏輯上沒有問題,但是如果另外伺服器上的springboot通過lettuce訪問這個redis哨兵,則得到的master地址為127.0.0.1,也就是springboot所在伺服器本機,這顯然就有問題了。
附springboot2.1 redis哨兵配置:
坑3:要注意配置文件.conf會被哨兵修改
redis-cli -h localhost -p 26379 ,可以登到sentinel上用info命令查看一下哨兵的信息。
曾經遇到過這樣一個問題,大致的信息如下
slaves莫名其妙多了一個,master的地址也明明改了真實對外的地址,這里又變成127.0.0.1 !
最後,把5個redis進程都停掉,逐個檢查配置文件,發現redis的配置文件在主從哨兵模式會被修改,master的配置文件最後邊莫名其妙多了一行replicaof 127.0.0.1 7001, 懷疑應該是之前配置錯誤的時候(見坑2)被哨兵動態加上去的! 總之,實踐中一定要多注意配置文件的變化。
(2)集群
當數據量大到一定程度,比如幾十上百G,哨兵模式不夠用了需要做水平拆分,早些年是使用codis,twemproxy這些第三方中間件來做分片的,即 客戶端 -> 中間件 -> Redis server 這樣的模式,中間件使用一致性Hash演算法來確定key在哪個分片上。後來Redis官方提供了方案,大家就都採用官方的Redis Cluster方案了。
Redis Cluster從邏輯上分16384個hash slot,分片演算法是 CRC16(key) mod 16384 得到key應該對應哪個slot,據此判斷這個slot屬於哪個節點。
每個節點可以設置1或多個從節點,常用的是3主節點3從節點的方案。
reshard,重新分片,可以指定從哪幾個節點移動一些hash槽到另一個節點去。重新分片的過程對客戶端透明,不影響線上業務。
搭建Redis cluster
redis.conf文件關鍵的幾個配置:
啟動6個集群節點
[root@VM_0_11_centos redis-6.0.3]# ps -ef|grep redis
root 5508 1 0 21:25 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7001 [cluster]
root 6903 1 0 21:32 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7002 [cluster]
root 6939 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7003 [cluster]
root 6966 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7004 [cluster]
root 6993 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7005 [cluster]
root 7015 1 0 21:33 ? 00:00:00 /usr/redis-6.0.3/src/redis-server 0.0.0.0:7006 [cluster]
這時候這6個節點還是獨立的,要把他們配置成集群:
說明: -a xxxx 是因為筆者在redis.conf中配置了requirepass xxxx密碼,然後 --cluster-replicas 1 中的1表示每個master節點有1個從節點。
上述命令執行完以後會有一個詢問: Can I set the above configuration? yes同意自動做好的分片即可。
最後 All 16384 slots covered. 表示集群中16384個slot中的每一個都有至少有1個master節點在處理,集群啟動成功。
查看集群狀態:
坑1:暴露給客戶端的節點地址不對
使用lettuce連接發現連不上,查看日誌 Connection refused: no further information: /127.0.0.1:7002 ,跟之前哨兵配置文件sentinel.conf里邊配置master地址犯的錯誤一樣,集群啟動的時候帶的地址應該是提供給客戶端訪問的地址。
我們要重建集群:先把6個redis進程停掉,然後刪除 nodes-7001.conf 這些節點配置文件,刪除持久化文件 mp.rdb 、 appendonly.aof ,重新啟動6個進程,在重新建立集群:
然後,還是連不上,這次報錯 connection timed out: /172.xx.0.xx:7004 ,發現連到企鵝雲伺服器的內網地址上了!
解決辦法,修改每個節點的redis.conf配置文件,找到如下說明:
所以增加配置:
然後再重新構建集群,停進程、改配置、刪除節點文件和持久化文件、啟動進程、配置集群。。。再來一套(累死了)
重新使用Lettuce測試,這次終於連上了!
坑2:Lettuce客戶端在master節點故障時沒有自動切換到從節點
name這個key在7002上,kill這個進程模擬master下線,然後Lettuce一直重連。我們期望的是應該能自動切換到其slave 7006上去,如下圖:
重新啟動7002進程,
7006已成為新master,7002成為它的slave,然後Lettuce也能連接上了。
解決辦法,修改Lettuce的配置:
筆者用的是springboot 2.1 spring-boot-starter-data-redis 默認的Lettuce客戶端,當使用Redis cluster集群模式時,需要配置一下 RedisConnectionFactory 開啟自適應刷新來做故障轉移時的自動切換從節點進行連接。
重新測試:停掉master 7006,這次Lettuce可以正常切換連到7002slave上去了。(仍然會不斷的在日誌里報連接錯誤,因為需要一直嘗試重連7006,但因為有7002從節點頂上了、所以應用是可以正常使用的)
Redis不保證數據的強一致性
Redis並不保證數據的強一致性,也就是取CAP定理中的AP
關於一致性Hash演算法,可以參考 一致性Hash演算法 - (jianshu.com)
Redis cluster使用的是hash slot演算法,跟一致性Hash演算法不太一樣,固定16384個hash槽,然後計算key落在哪個slot里邊(計算key的CRC16值再對16384取模),key找的是slot而不是節點,而slot與節點的對應關系可以通過reshard改變並通過gossip協議擴散到集群中的每一個節點、進而可以為客戶端獲知,這樣key的節點定址就跟具體的節點個數沒關系了。也同樣解決了普通hash取模演算法當節點個數發生變化時,大量key對應的定址都發生改動導致緩存失效的問題。
比如集群增加了1個節點,這時候如果不做任何操作,那麼新增加的這個節點上是沒有slot的,所有slot都在原來的節點上且對應關系不變、所以沒有因為節點個數變動而緩存失效,當reshard一部分slot到新節點後,客戶端獲取到新遷移的這部分slot與新節點的對應關系、定址到新節點,而沒遷移的slot仍然定址到原來的節點。
關於熱遷移,猜想,內部應該是先做復制遷移,等遷移完了,再切換slot與節點的對應關系,復制沒有完成之前仍按照原來的slot與節點對應關系去原節點訪問。復制結束之後,再刪除原節點上已經遷移的slot所對應的key。
與哨兵模式比較類似,當1個節點發現某個master節點故障了、會對這個故障節點進行pfail主觀宕機,然後會通過gossip協議通知到集群中的其他節點、其他節點也執行判斷pfail並gossip擴散廣播這一過程,當超過半數節點pfail時那麼故障節點就是fail客觀宕機。接下來所有的master節點會在故障節點的從節點中選出一個新的主節點,此時所有的master節點中超過半數的都投票選舉了故障節點的某個從節點,那麼這個從節點當選新的master節點。
所有節點都持有元數據,節點之間通過gossip這種二進制協議進行通信、發送自己的元數據信息給其他節點、故障檢測、集群配置更新、故障轉移授權等等。
這種去中心化的分布式節點之間內部協調,包括故障識別、故障轉移、選主等等,核心在於gossip擴散協議,能夠支撐這樣的廣播協議在於所有的節點都持有一份完整的集群元數據,即所有的節點都知悉當前集群全局的情況。
Redis高可用方案 - (jianshu.com)
面試題:Redis 集群模式的工作原理能說一下么 - 雲+社區 - 騰訊雲 (tencent.com)
深度圖解Redis Cluster原理 - detectiveHLH - 博客園 (cnblogs.com)
Redis學習筆記之集群重啟和遇到的坑-阿里雲開發者社區 (aliyun.com)
雲伺服器Redis集群部署及客戶端通過公網IP連接問題
B. php 中如何使用緩存,使用哪種緩存機制最好;
php的緩存三種.有文件緩存,資料庫緩存,memcache緩存;
memcache緩存要求對伺服器支持,而且它的緩存是由期限的,一般是30天。這種緩存的效率是最高的。讀存取的速度最快。
資料庫緩存
和
文件緩存比較簡單。適用小的項目。和php新手
C. 分布式存儲是什麼
分布式存儲系統,是將數據分散存儲在多台獨立的設備上。傳統的網路存儲系統採用集中的存儲伺服器存放所有數據,存儲伺服器成為系統性能的瓶頸,也是可靠性和安全性的焦點,不能滿足大規模存儲應用的需要。分布式網路存儲系統採用可擴展的系統結構,利用多台存儲伺服器分擔存儲負荷,利用位置伺服器定位存儲信息,它不但提高了系統的可靠性、可用性和存取效率,還易於擴展。
分布式和集中式存儲
集中存儲的優缺點是,物理介質集中布放;視頻流上傳到中心對機房環境要求高,要求機房空間大,承重、空調等都是需要考慮的問題。
分布存儲,集中管理的優缺點是,物理介質分布到不同的地理位置;視頻流就近上傳,對骨幹網帶寬沒有什麼要求;可採用多套低端的小容量的存儲設備分布部署,設備價格和維護成本較低;小容量設備分布部署,對機房環境要求低。
鏈喬教育在線旗下學碩創新區塊鏈技術工作站是中國教育部學校規劃建設發展中心開展的「智慧學習工場2020-學碩創新工作站 」唯一獲準的「區塊鏈技術專業」試點工作站。專業站立足為學生提供多樣化成長路徑,推進專業學位研究生產學研結合培養模式改革,構建應用型、復合型人才培養體系。
D. Spring本地緩存的使用方法
我們現在在用的Spring Cache,可以直接看Spring Boot提供的緩存枚舉類,有如下這些:
EhCache:一個純Java的進程內緩存框架,所以也是基於本地緩存的。(注意EhCache2.x和EhCache3.x相互不兼容)。
Redis:分布式緩存,只有Client-Server(CS)模式,Java一般使用Jedis/Luttuce來操縱。
Hazelcast:基於內存的數據網格。雖然它基於內存,但是分布式應用程序可以使用Hazelcast進行分布式緩存、同步、集群、處理、發布/訂閱消息等。
Guava:它是Google Guava工具包中的一個非常方便易用的本地化緩存實現,基於LRU(最近最少使用)演算法實現,支持多種緩存過期策略。在Spring5.X以後的版本已經將他標記為過期了。
Caffeine:是使用Java8對Guava緩存的重寫版本,在Spring5中將取代了Guava,支持多種緩存過期策略。
SIMPLE:使用ConcurrentMapCacheManager,因為不支持緩存過期時間,所以做本地緩存基本不考慮該方式。
關於分布式緩存,我們需要後面會專門討論Redis的用法,這里只看本地緩存。性能從高到低,依次是Caffeine,Guava,ConcurrentMapCacheManager,其中Caffeine在讀寫上都快了Guava近一倍。
這里我們只討論在Spring Boot裡面怎麼整合使用Caffeine和EhCache。
主要有以下幾個步驟:
1)加依賴包:
2)配置緩存:
這里有兩種方法,通過文件配置或者在配置類裡面配置,先看一下文件配置,我們可以寫一個properties文件,內容像這樣:
然後還要在主類中加上@EnableCaching註解:
另外一種更靈活的方法是在配置類中配置:
應用類:
測試類:
導入依賴包,分為2.x版本和3.x版本。
其中2.x版本做如下導入:
3.x版本做如下導入:
導包完成後,我們使用JCacheManagerFactoryBean + ehcache.xml的方式配置:
參考資料:
https://blog.csdn.net/f641385712/article/details/94982916
http://www.360doc.com/content/17/1017/20/16915_695800687.shtml
E. 大數據環境下分布式文件系統有哪些特點,相應的優化思路是什麼
分布式元數據管理:分布式元數據管理主要通過元數據服務分布式部署的方式,實現了元數據分布式管理,解決一般分布式文件系統的單元數據服務節點導致的響應用戶請求效率不高、存儲文件數目受限和單點故障等問題,具有降低用戶請求處理延遲,提高分布式文件系統的可擴展性和可用性的特性。一般包括完全分布式架構、元數據訪問負載均衡、元數據伺服器高效索引、元數據伺服器彈性伸縮等技術點。
多層級存儲管理:多層級存儲管理用於實現內存 / SSD/HDD 等異構存儲設備的池化管理,以及各類存儲設備的動態接入管理,通過設備抽象和提供統一命名空間,面向分布式文件系統提供統一的存儲資源池,支持熱點數據自動感知和智能化存儲調度,最大程度提升數據存儲與訪問的效能。一般包括異構存儲設備管理、多存儲系統適配、統一命名空間、基於熱度的存儲資源調度等技術點。
數據一致性保障:數據一致性保障主要解決分布式文件系統中多副本和緩存等在數據存儲與訪問過程中的一致性問題,通過構建數據一致性模型、進行數據一致性校驗等方式,保障數據在存儲和訪問過程中的一致性,在提升數據訪問性能的同時確保數據存儲和訪問的正確性。一般包括一致性協議優化、一致性檢驗等技術點。
高並行讀寫優化:高並行讀寫優化用於提高分布式文件讀寫的並行化水平,最大化提升分布式文件系統下的數據訪問效率。一般包括分布式數據訪問緩存管理和調度演算法優化、IO 演算法優化和合並 IO 等技術點。
分布式散列與動態均衡:分布式散列與動態均衡實現分布式文件系統下高性能的數據塊定位,提高數據訪問性能,以及數據塊的遷移和再平衡,提升分布式文件系統的穩定性和可持續服務能力。一般包括基於一致性哈希的數據塊索引管理、動態數據再平衡等技術點。
存儲高可用:存儲高可用通過數據多副本技術、狀態自檢測和自修復、核心服務分布式部署等技術手段,實現自動檢測分布式文件系統中的各種錯誤和失效,並且在文件系統出現錯誤和失效時可自行進行多副本間的數據修復,最終持續向用戶提供正常的數據訪問服務。一般包括可配置數據多副本、數據自恢復及自維護等技術點。
海量小文件高性能存儲訪問:海量小文件高性能存儲訪問主要採用小文件匯集成大文件進行存儲、細粒度二級索引管理等技術,實現在現有分布式文件系統的基礎上,擴展對海量小文件的存儲與訪問的能力,同時解決小文件的隨機讀寫問題,大大提高分布式文件系統對海量小文件的存儲訪問效率。
F. 如何實現高性能分布式文件存儲
其實分布式文件存儲,最復雜的就是元數據的保存和處理,而我使用的XGFS文件存儲軟體只需要三個全快閃記憶體元數據高可用節點,就可以高效保存和處理 100 億文件規模的數據,可以靈活擴展,滿足公司不斷增長的業務對性能和容量的需求,XSKY星辰天合這款產品還是很有性價比的。
G. 存儲器層次結構中的緩存
《深入理解計算機系統》p422
6.1 存儲器層次結構中的緩存
一般而言,高速緩存( cache ,讀作「 cash 」)是一個小而快速的存儲設備,它作為存儲在更大、也更慢的設備中的數據對象的緩沖區域。使用高速緩存的過程稱為緩存( caching ,讀作「 cashing 」)。存儲器層次結構的中心思想是,對於每個 k ,位於 k 層的更快更小的存儲設備作為位於 k 十1層的更大更慢的存儲設備的緩存。換句話說,層次結構中的每一層都緩存來自較低一層的數據對象。例如,本地磁碟作為通過網路從遠程磁碟取出的文件(例如 Web 頁面)的緩存,主存作為本地磁碟上數據的緩存,依此類推,直到最小的緩存—— CPU 寄存器組。圖6-22展示了存儲器層次結構中緩存的一般性概念。第 k 十1層的存儲器被劃分成連續的數據對象組塊( chunk ),稱為塊( block )。每個塊都有一個唯一的地址或名字,使之區別於其他的塊。塊可以是固定大小的(通常是這樣的),也可以是可變大小的(例如存儲在 Web 伺服器上的遠程 HTML 文件)。例如,圖6-22中第 k 十1層存儲器被劃分成16個大小固定的塊,編號為0~15。
類似地,第 k 層的存儲器被劃分成較少的塊的集合,每個塊的大小與 k 十1層的塊的大小一樣。在任何時刻,第 k 層的緩存包含第 k 十1層塊的一個子集的副本。例如,在圖6-22中,第 k 層的緩存有4個塊的空間,當前包含塊4、9、14和3的副本。
數據總是以塊大小為傳送單元( transfer unit )在第 k 層和第 k +1層之間來回復制的。雖然在層次結構中任何一對相鄰的層次之間塊大小是固定的,但是其他的層次對之間可以有不同的塊大小。例如,在圖6-21中,L1和 LO 之間的傳送通常使用的是1個字大小的塊。L2和L1之間(以及I3和I2之間、L4和I3之間)的傳送通常使用的是幾十個位元組的
塊。而L5和L4之間的傳送用的是大小為幾百或幾千位元組的塊。一般而言,層次結構中較低層(離 CPU 較遠)的設備的訪問時間較長,因此為了補償這些較長的訪問時間,傾向於使用較大的塊。
1. 緩存命中
當程序需要第 k 十1層的某個數據對象 d 時,它首先在當前存儲在第 k 層的一個塊中查找 d 。如果 d 剛好緩存在第 k 層中,那麼就是我們所說的緩存命中( cache hit )。該程序直接從第 k 層讀取 d ,根據存儲器層次結構的性質,這要比從第 k +1層讀取 d 更快。例如,一個有良好時間局部性的程序可以從塊14中讀出一個數據對象,得到一個對第 k 層的緩存命中。
2. 緩存不命中
另一方面,如果第 k 層中沒有緩存數據對象 d ,那麼就是我們所說的緩存不命中( cache miss )。當發生緩存不命中時,第 k 層的緩存從第 k 十1層緩存中取出包含 d 的那個塊,如果第 k 層的緩存已經滿了,可能就會覆蓋現存的一個塊。
覆蓋一個現存的塊的過程稱為替換( replacing )或驅逐( evicting )這個塊。被驅逐的這個塊有時也稱為犧牲塊( victim block )。決定該替換哪個塊是由緩存的替換策略( replace — ment policy )來控制的。例如,一個具有隨機替換策略的緩存會隨機選擇一個犧牲塊。一個具有最近最少被使用 LRU )替換策略的緩存會選擇那個最後被訪問的時間距現在最遠的塊。
在第 k 層緩存從第 k 十1層取出那個塊之後,程序就能像前面一樣從第 k 層讀出 d 了。例如,在圖6-22中,在第 k 層中讀塊12中的一個數據對象,會導致一個緩存不命中,因為塊12當前不在第 k 層緩存中。一旦把塊12從第 k 十1層復制到第 k 層之後,它就會保持在那裡,等待稍後的訪問。
3. 緩存不命中的種類
區分不同種類的緩存不命中有時候是很有幫助的。如果第 k 層的緩存是空的,那麼對
任何數據對象的訪問都會不命中。一個空的緩存有時被稱為冷緩存( cold cache ),此類不命中稱為強制性不命中( compulsory miss )或冷不命中( cold miss )。冷不命中很重要,因為它們通常是短暫的事件,不會在反復訪問存儲器使得緩存暖身( warmed up )之後的穩定狀態中出現。
只要發生了不命中,第 k 層的緩存就必須執行某個放置策略( placement policy ),確定把它從第 k 十1層中取出的塊放在哪裡。最靈活的替換策略是允許來自第 k +1層的任何塊放在第 k 層的任何塊中。對於存儲器層次結構中高層的緩存(靠近 CPU ),它們是用硬體來實現的,而且速度是最優的,這個策略實現起來通常很昂貴,因為隨機地放置塊,定位起來代價很高。
因此,硬體緩存通常使用的是更嚴格的放置策略,這個策略將第 k 十1層的某個塊限制放置在第 k 層塊的一個小的子集中(有時只是一個塊)。例如,在圖6-22中,我們可以確定第 k 十1層的塊 i 必須放置在第 k 層的塊( i mod 4)中。例如,第 k 十1層的塊0、4、8和12會映射到第 k 層的塊0;塊1、5、9和13會映射到塊1;依此類推。注意,圖6-22中的示例緩存使用的就是這個策略。
這種限制性的放置策略會引起一種不命中,稱為沖突不命中( conflict miss ),在這種情況中,緩存足夠大,能夠保存被引用的數據對象,但是因為這些對象會映射到同一個緩存塊,緩存會一直不命中。例如,在圖6-22中,如果程序請求塊0,然後塊8,然後塊0,然後塊8,依此類推,在第 k 層的緩存中,對這兩個塊的每次引用都會不命中,即使這個緩存總共可以容納4個塊。
程序通常是按照一系列階段(如循環)來運行的,每個階段訪問緩存塊的某個相對穩定不變的集合。例如,一個嵌套循環可能會反復地訪問同一個數組的元素。這個塊的集合稱為這個階段的工作集( working set )。當工作集的大小超過緩存的大小時,緩存會經歷容量不命中( capacity miss )。換句話說就是,緩存太小了,不能處理這個工作集。
4. 緩存管理
正如我們提到過的,存儲器層次結構的本質是,每一層存儲設備都是較低一層的緩存。在每一層上,某種形式的邏輯必須管理緩存。這里,我們的意思是指某個東西要將緩存劃分成塊,在不同的層之間傳送塊,判定是命中還是不命中,並處理它們。管理緩存的邏輯可以是硬體、軟體,或是兩者的結合。
例如,編譯器管理寄存器文件,緩存層次結構的最高層。它決定當發生不命中時何時發射載入,以及確定哪個寄存器來存放數據。L1、L2和L3層的緩存完全是由內置在緩存中的硬體邏輯來管理的。在一個有虛擬內存的系統中, DRAM 主存作為存儲在磁碟上的數據塊的緩存,是由操作系統軟體和 CPU 上的地址翻譯硬體共同管理的。對於一個具有像 AFS 這樣的分布式文件系統的機器來說,本地磁碟作為緩存,它是由運行在本地機器上的 AFS 客戶端進程管理的。在大多數時候,緩存都是自動運行的,不需要程序採取特殊的或顯式的行動。
6.3.2 存儲器層次結構概念小結
概括來說,基於緩存的存儲器層次結構行之有效,是因為較慢的存儲設備比較快的存儲設備更便宜,還因為程序傾向於展示局部性:
1)利用時間局部性: 由於時間局部性,同一數據對象可能會被多次使用。一旦一個數據對象在第一次不命中時被復制到緩存中,我們就會期望後面對該目標有一系列的訪問命中。因為緩存比低一層的存儲設備更快,對後面的命中的服務會比最開始的不命中快很多。
2)利用空間局部性: 塊通常包含有多個數據對象。由於空間局部性,我們會期望後面對該塊中其他對象的訪問能夠補償不命中後復制該塊的花費。現代系統中到處都使用了緩存。正如從圖6-23中能夠看到的那樣, CPU 晶元、操作系統、分布式文件系統中和萬維網上都使用了緩存。各種各樣硬體和軟體的組合構成和管理著緩存。注意,圖6-23中有大量我們還未涉及的術語和縮寫。在此我們包括這些術語和縮寫是為了說明緩存是多麼的普遍。
H. 分布式文件存儲系統採用什麼方式
一。分布式Session的幾種實現方式 1.基於資料庫的Session共享 2.基於NFS共享文件系統 3.基於memcached 的session,如何保證 memcached 本身的高可用性? 4. 基於resin/tomcat web容器本身的session復制機制 5. 基於TT/Redis 或 jbosscache 進行 session 共享。 6. 基於cookie 進行session共享 或者是: 一、Session Replication 方式管理 (即session復制) 簡介:將一台機器上的Session數據廣播復制到集群中其餘機器上 使用場景:機器較少,網路流量較小 優點:實現簡單、配置較少、當網路中有機器Down掉時不影響用戶訪問 缺點:廣播式復制到其餘機器有一定廷時,帶來一定網路開銷 二、Session Sticky 方式管理 簡介:即粘性Session、當用戶訪問集群中某台機器後,強制指定後續所有請求均落到此機器上 使用場景:機器數適中、對穩定性要求不是非常苛刻 優點:實現簡單、配置方便、沒有額外網路開銷 缺點:網路中有機器Down掉時、用戶Session會丟失、容易造成單點故障 三、緩存集中式管理 簡介:將Session存入分布式緩存集群中的某台機器上,當用戶訪問不同節點時先從緩存中拿Session信息 使用場景:集群中機器數多、網路環境復雜 優點:可靠性好 缺點:實現復雜、穩定性依賴於緩存的穩定性、Session信息放入緩存時要有合理的策略寫入 二。Session和Cookie的區別和聯系以及Session的實現原理 1、session保存在伺服器,客戶端不知道其中的信息;cookie保存在客戶端,伺服器能夠知道其中的信息。 2、session中保存的是對象,cookie中保存的是字元串。 3、session不能區分路徑,同一個用戶在訪問一個網站期間,所有的session在任何一個地方都可以訪問到。而cookie中如果設置了路徑參數,那麼同一個網站中不同路徑下的cookie互相是訪問不到的。 4、session需要藉助cookie才能正常<nobr oncontextmenu="return false;" onmousemove="kwM(3);" id="key3" onmouseover="kwE(event,3, this);" style="COLOR: #6600ff; BORDER-BOTTOM: 0px dotted; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" onclick="return kwC();" onmouseout="kwL(event, this);" target="_blank">工作</nobr>。如果客戶端完全禁止cookie,session將失效。 http是無狀態的協議,客戶每次讀取web頁面時,伺服器都打開新的會話,而且伺服器也不會自動維護客戶的上下文信息,那麼要怎麼才能實現網上商店中的 購物車呢,session就是一種保存上下文信息的機制,它是針對每一個用戶的,變數的值保存在伺服器端,通過SessionID來區分不同的客 戶,session是以cookie或URL重寫為基礎的,默認使用cookie來實現,系統會創造一個名為JSESSIONID的輸出cookie,我 們叫做session cookie,以區別persistent cookies,也就是我們通常所說的cookie,注意session cookie是存儲於瀏覽器內存中的,並不是寫到硬碟上的,這也就是我們剛才看到的JSESSIONID,我們通常情是看不到JSESSIONID的,但 是當我們把瀏覽器的cookie禁止後,web伺服器會採用URL重寫的方式傳遞Sessionid,我們就可以在地址欄看到 sessionid=KWJHUG6JJM65HS2K6之類的字元串。 明白了原理,我們就可以很容易的分辨出persistent cookies和session cookie的區別了,網上那些關於兩者安全性的討論也就一目瞭然了,session cookie針對某一次會話而言,會話結束session cookie也就隨著消失了,而persistent cookie只是存在於客戶端硬碟上的一段文本(通常是加密的),而且可能會遭到cookie欺騙以及針對cookie的跨站腳本攻擊,自然不如 session cookie安全了。 通常session cookie是不能跨窗口使用的,當你新開了一個瀏覽器窗口進入相同頁面時,系統會賦予你一個新的sessionid,這樣我們信息共享的目的就達不到 了,此時我們可以先把sessionid保存在persistent cookie中,然後在新窗口中讀出來,就可以得到上一個窗口SessionID了,這樣通過session cookie和persistent cookie的結合我們就實現了跨窗口的session tracking(會話跟蹤)。 在一些web開發的書中,往往只是簡單的把Session和cookie作為兩種並列的http傳送信息的方式,session cookies位於伺服器端,persistent cookie位於客戶端,可是session又是以cookie為基礎的,明白的兩者之間的聯系和區別,我們就不難選擇合適的技術來開發web service了。 總之: 一、cookie機制和session機制的區別 具體來說cookie機制採用的是在客戶端保持狀態的方案,而session機制採用的是在伺服器端保持狀態的方案。 同時我們也看到,由於在伺服器端保持狀態的方案在客戶端也需要保存一個標識,所以session機制可能需要藉助於cookie機制來達到保存標識的目的,但實際上還有其他選擇。 二、會話cookie和持久cookie的區別 如果不設置過期時間,則表示這個cookie生命周期為瀏覽器會話期間,只要關閉瀏覽器窗口,cookie就消失了。這種生命期為瀏覽會話期的cookie被稱為會話cookie。會話cookie一般不保存在硬碟上而是保存在內存里。 如果設置了過期時間,瀏覽器就會把cookie保存到硬碟上,關閉後再次打開瀏覽器,這些cookie依然有效直到超過設定的過期時間。 存儲在硬碟上的cookie可以在不同的瀏覽器進程間共享,比如兩個IE窗口。而對於保存在內存的cookie,不同的瀏覽器有不同的處理方式。 三、如何利用實現自動登錄 當用戶在某個網站注冊後,就會收到一個惟一用戶ID的cookie。客戶後來重新連接時,這個用戶ID會自動返回,伺服器對它進行檢查,確定它是否為注冊用戶且選擇了自動登錄,從而使用戶無需給出明確的用戶名和密碼,就可以訪問伺服器上的資源。 四、如何根據用戶的愛好定製站點 網站可以使用cookie記錄用戶的意願。對於簡單的設置,網站可以直接將頁面的設置存儲在cookie中完成定製。然而對於更復雜的定製,網站只需僅將一個惟一的標識符發送給用戶,由伺服器端的資料庫存儲每個標識符對應的頁面設置。 五、cookie的發送 1.創建Cookie對象 2.設置最大時效 3.將Cookie放入到HTTP響應報頭 如果你創建了一個cookie,並將他發送到瀏覽器,默認情況下它是一個會話級別的cookie:存儲在瀏覽器的內存中,用戶退出瀏覽器之後被刪除。如 果你希望瀏覽器將該cookie存儲在磁碟上,則需要使用maxAge,並給出一個以秒為單位的時間。將最大時效設為0則是命令瀏覽器刪除該 cookie。 發送cookie需要使用HttpServletResponse的addCookie方法,將cookie插入到一個 Set-Cookie HTTP請求報頭中。由於這個方法並不修改任何之前指定的Set-Cookie報頭,而是創建新的報頭,因此我們將這個方法稱為是addCookie,而 非setCookie。同樣要記住響應報頭必須在任何文檔內容發送到客戶端之前設置。 六、cookie的讀取 1.調用request.getCookie 要獲取有瀏覽器發送來的cookie,需要調用HttpServletRequest的getCookies方法,這個調用返回Cookie對象的數組,對應由HTTP請求中Cookie報頭輸入的值。 2.對數組進行循環,調用每個cookie的getName方法,直到找到感興趣的cookie為止 cookie與你的主機(域)相關,而非你的servlet或JSP頁面。因而,盡管你的servlet可能只發送了單個cookie,你也可能會得到許多不相關的cookie。 例如: String cookieName = 「userID」; Cookie cookies[] = request.getCookies(); if (cookies!=null){ for(int i=0;i Cookie cookie = cookies[i]; if (cookieName.equals(cookie.getName())){ doSomethingWith(cookie.getValue()); } } } 七、如何使用cookie檢測初訪者 A.調用HttpServletRequest.getCookies()獲取Cookie數組 B.在循環中檢索指定名字的cookie是否存在以及對應的值是否正確 C.如果是則退出循環並設置區別標識 D.根據區別標識判斷用戶是否為初訪者從而進行不同的操作 八、使用cookie檢測初訪者的常見錯誤 不能僅僅因為cookie數組中不存在在特定的數據項就認為用戶是個初訪者。如果cookie數組為null,客戶可能是一個初訪者,也可能是由於用戶將cookie刪除或禁用造成的結果。 但是,如果數組非null,也不過是顯示客戶曾經到過你的網站或域,並不能說明他們曾經訪問過你的servlet。其它servlet、JSP頁面以及 非Java Web應用都可以設置cookie,依據路徑的設置,其中的任何cookie都有可能返回給用戶的瀏覽器。 正確的做法是判斷cookie數組是否為空且是否存在指定的Cookie對象且值正確。 九、使用cookie屬性的注意問題 屬性是從伺服器發送到瀏覽器的報頭的一部分;但它們不屬於由瀏覽器返回給伺服器的報頭。 因此除了名稱和值之外,cookie屬性只適用於從伺服器輸出到客戶端的cookie;伺服器端來自於瀏覽器的cookie並沒有設置這些屬性。 因而不要期望通過request.getCookies得到的cookie中可以使用這個屬性。這意味著,你不能僅僅通過設置cookie的最大時效, 發出它,在隨後的輸入數組中查找適當的cookie,讀取它的值,修改它並將它存回Cookie,從而實現不斷改變的cookie值。 十、如何使用cookie記錄各個用戶的訪問計數 1.獲取cookie數組中專門用於統計用戶訪問次數的cookie的值 2.將值轉換成int型 3.將值加1並用原來的名稱重新創建一個Cookie對象 4.重新設置最大時效 5.將新的cookie輸出 十一、session在不同環境下的不同含義 session,中文經常翻譯為會話,其本來的含義是指有始有終的一系列動作/消息,比如打電話是從拿起電話撥號到掛斷電話這中間的一系列過程可以稱之為一個session。 然而當session一詞與網路協議相關聯時,它又往往隱含了「面向連接」和/或「保持狀態」這樣兩個含義。 session在Web開發環境下的語義又有了新的擴展,它的含義是指一類用來在客戶端與伺服器端之間保持狀態的解決方案。有時候Session也用來指這種解決方案的存儲結構。 十二、session的機制 session機制是一種伺服器端的機制,伺服器使用一種類似於散列表的結構(也可能就是使用散列表)來保存信息。 但程序需要為某個客戶端的請求創建一個session的時候,伺服器首先檢查這個客戶端的請求里是否包含了一個session標識-稱為session id,如果已經包含一個session id則說明以前已經為此客戶創建過session,伺服器就按照session id把這個session檢索出來使用(如果檢索不到,可能會新建一個,這種情況可能出現在服務端已經刪除了該用戶對應的session對象,但用戶人為 地在請求的URL後面附加上一個JSESSION的參數)。 如果客戶請求不包含session id,則為此客戶創建一個session並且生成一個與此session相關聯的session id,這個session id將在本次響應中返回給客戶端保存。 十三、保存session id的幾種方式 A.保存session id的方式可以採用cookie,這樣在交互過程中瀏覽器可以自動的按照規則把這個標識發送給伺服器。 B. 由於cookie可以被人為的禁止,必須有其它的機制以便在cookie被禁止時仍然能夠把session id傳遞回伺服器,經常採用的一種技術叫做URL重寫,就是把session id附加在URL路徑的後面,附加的方式也有兩種,一種是作為URL路徑的附加信息,另一種是作為查詢字元串附加在URL後面。網路在整個交互過程中始終 保持狀態,就必須在每個客戶端可能請求的路徑後面都包含這個session id。 C.另一種技術叫做表單隱藏欄位。就是伺服器會自動修改表單,添加一個隱藏欄位,以便在表單提交時能夠把session id傳遞回伺服器。 十四、session什麼時候被創建 一個常見的錯誤是以為session在有客戶端訪問時就被創建,然而事實是直到某server端程序(如Servlet)調用HttpServletRequest.getSession(true)這樣的語句時才會被創建。 十五、session何時被刪除 session在下列情況下被刪除: A.程序調用HttpSession.invalidate() B.距離上一次收到客戶端發送的session id時間間隔超過了session的最大有效時間 C.伺服器進程被停止 再次注意關閉瀏覽器只會使存儲在客戶端瀏覽器內存中的session cookie失效,不會使伺服器端的session對象失效。