當前位置:首頁 » 編程軟體 » lru腳本

lru腳本

發布時間: 2022-09-21 01:46:33

『壹』 java web開發緩存方案,ehcache和redis哪個更好

這里就不再逐個討論了,我將會在一個實際應用程序開發場景中介紹其中的一些。使用Redis作為一個緩存解決方案我之前提到過,Redis可輕易地用作一個緩存解決方案,碰巧我現在正好需要這樣一個!在該應用程序示例中,我將Redis集成到我基於定位的移動Web服務中,稱之為Magnus。如果您沒有關注本系列,那麼我會先使用Play框架實現Magnus,從那時起我就已經在各種實現中開發和重構它了。Magnus是一個簡單服務,可以通過HTTPPUT請求使用JSON文檔。這些文檔描述了特定帳號的位置,表示持有移動設備的人。現在,我想要將緩存集成到Magnus,也就是說我想要通過將不常更改的數據存儲在內存中以減少I/O流量。Magnus緩存!在清單5中的第一步中,可以通過get調用了解新引入的帳戶名稱(一個鍵)是否為REdis中的一個鍵。get調用可以將帳戶ID作為一個值返回,或者將返回null。如果返回一個值,我將用其作為我的acctId變數。如果返回的是null(表明該帳戶名稱不是Redis中一個鍵),那麼我將在MongoDB查找該帳戶值,並通過set命令將其添加到Redis。這里的優勢是速度:接下來,被請求的帳戶將提交一個位置,這樣我就能夠從Redis中獲取其ID(作為內存緩存),而不是轉到MongoDB並帶來額外讀取I/O成本。清單5.使用Redis作為內存緩存"/location/:account"{put{defjacksonMapper=newObjectMapper()defjson=jacksonMapper.readValue(request.contentText,Map.class)defformatter=newSimpleDateFormat("dd-MM-yyyyHH:mm")defdt=formatter.parse(json['timestamp'])defres=[:]try{defjedis=pool.getResource()defacctId=jedis.get(request.parameters['account'])if(!acctId){defacct=Account.findByName(request.parameters['account'])jedis.set(request.parameters['account'],acct.id.toString())acctId=acct.id}pool.returnResource(jedis)newLocation(acctId.toString(),dt,json['latitude'].doubleValue(),json['longitude'].doubleValue()).save()res['status']='success'}catch(exp){res['status']="error${exp.message}"}response.json=jacksonMapper.writeValueAsString(res)}}注意,清單5中的aMagnus實現(使用Groovy編寫)仍然使用一個Nosql實現作為數據模型存儲;它僅僅使用Redis作為一個緩存實現用於查詢數據。因為我的主要帳戶數據位於MongoDB中(事實上,它駐留在MongoHQ.com中),而我的Redis數據存儲在本地運行。在隨後查找帳戶ID時,Magnus速度將顯著提升。可是等等!我為什麼同時需要MongoDB和Redis?難道我就不能單獨使用一個嗎?ORM的Node.js很多項目均提供ORM類映射用於Redis,其中包括一個極富影響力的基於Ruby的備用方案,稱為Ohm。我檢查了該項目基於Java的派生產品(稱為JOhm),但是最終決定使用一個為Node編寫的派生產品。Ohm及其派生項目的妙處在於他們允許您將一個對象模型映射到一個基於Redis的數據結構。因此,您的模型對象是持久性的,同時在大多數情況下其讀取速度也非常之快。有了Nohm,我便能夠使用JavaScript快速重寫我的Magnus應用程序並能立即持久化Location對象。在清單6中,我已定義了一個Location模型,該模型包括3個屬性。(注意,我通過將timestamp設置為一個字元串而不是一個真實的時間戳,從而簡化我的示例。)清單6.Node.js中的RedisORMvarLocation=nohm.model('Location',{properties:{latitude:{type:'float',unique:false,validations:[['notEmpty']]},longitude:{type:'float',unique:false,validations:[['notEmpty']]},timestamp:{type:'string',unique:false,validations:[['notEmpty']]}}});Node的Express框架使NohmLocation對象的使用變得十分簡單。在我的應用程序PUT實現中,我可以捕獲正在進入的JSON值,並通過Nohm的p調用將其導入到一個Location實例。然後我再檢查該示例是否有效,如果有效,我會對其進行持久化。清單7.在Node的Express.js中使用Nohmapp.put('/',function(req,res){res.contentType('json');varlocation=newLocation;location.p("timestamp",req.body.timestamp);location.p("latitude",req.body.latitude);location.p("longitude",req.body.longitude);if(location.valid()){location.save(function(err){if(!err){res.send(JSON.stringify({status:"success"}));}else{res.send(JSON.stringify({status:location.errors}));}});}else{res.send(JSON.stringify({status:location.errors}));}});正如清單7所示,可以輕易地將Redis構建成一個極其快速的內存數據存儲。在一些案例中,它甚至是一個比memcached更好的緩存!結束語Redis對於許多數據存儲場景非常有用,因為它可以將數據持久化到磁碟(還因為它支持一個豐富的數據集),有時候,它是memcached的有力競爭對手。有些情況下,對於您的領域也是很有意義的,您可以使用Redis作為數據模型和隊列的一個備份存儲。Redis客戶端實現幾乎可被移植到任何編程語言中。Redis不是RDMBS的完全替代品,也不是一個重量級存儲,但是和MongoDB一樣擁有豐富的功能。然而,在很多情況下,它可與這些技術共存。

『貳』 oracle的字典緩存命中率是什麼意思


1、 ORACLE 實例――包括內存結構與後台進程 2、 ORACLE 資料庫――物理操作系統文件的集合 3、 了解內存結構的組成 4、 了解後台進程的作用

1、 Oracle 實例――包括內存結構與後台進程
2、 Oracle 資料庫――物理操作系統文件的集合
3、 了解內存結構的組成
4、 了解後台進程的作用
5、 了解資料庫的物理文件
6、 解釋各種邏輯結構

一、Oracle實例

1、Oracle 實例

System Global Area(SGA) 和 Background Process 稱為資料庫的實例。

2、Oracle 資料庫

一系列物理文件的集合(數據文件,控制文件,聯機日誌,參數文件等)

3、系統全局共享區System Global Area(SGA)

System Global Area 是一塊巨大的共享內存區域,他被看做是Oracle 資料庫的一個大緩沖池,這里的數據可以被Oracle的各個進程共用。其大小可以通過如下語句查看:
SQL> select * from v$sga;
NAME VALUE
-------------------- ---------
Fixed Size 39816
Variable Size 259812784
Database Buffers 1.049E+09
Redo Buffers 327680

更詳細的信息可以參考V$sgastat、V$buffer_pool

主要包括以下幾個部分:

a、 共享池(Shared pool)

共享池是SGA中最關鍵的內存片段,特別是在性能和可伸縮性上。一個太小的共享池會扼殺性能,使系統停止,太大的共享池也會有同樣的效果,將會消耗大量的CPU來管理這個共享池。不正確的使用共享池只會帶來災難。共享池主要又可以分為以下兩個部分:

SQL語句緩沖(Library Cache)

當一個用戶提交一個SQL語句,Oracle會將這句SQL進行分析(parse),這個過程類似於編譯,會耗費相對較多的時間。在分析完這個SQL,Oracle會把他的分析結果給保存在Shared pool的Library Cache中,當資料庫第二次執行該SQL時,Oracle自動跳過這個分析過程,從而減少了系統運行的時間。這也是為什麼第一次運行的SQL 比第二次運行的SQL要慢一點的原因。

下面舉例說明parse的時間
SQL> select count(*) fromscpass ;
COUNT(*)
----------
243
Elapsed: 00:00:00.08

這是在Share_pool 和Data buffer 都沒有數據緩沖區的情況下所用的時間
SQL> alter system flush SHARED_POOL;
System altered.

清空Share_pool,保留Data buffer
SQL> select count(*) from scpass ;
COUNT(*)
----------
243
Elapsed: 00:00:00.02
SQL> select count(*) from scpass ;
COUNT(*)
----------
243
Elapsed: 00:00:00.00

從兩句SQL 的時間差上可以看出該SQL 的Parse 時間約為00:00:00.02

對於保存在共享池中的SQL語句,可以從V$Sqltext、v$Sqlarea中查詢到,對於編程者來說,要盡量提高語句的重用率,減少語句的分析時間。一個設計的差的應用程序可以毀掉整個資料庫的Share pool,提高SQL語句的重用率必須先養成良好的變成習慣,盡量使用Bind變數。

數據字典緩沖區(Data Dictionary Cache)

顯而易見,數據字典緩沖區是Oracle特地為數據字典准備的一塊緩沖池,供Oracle內部使用,沒有什麼可以說的。

b、塊緩沖區高速緩存(Database Buffer Cache)

這些緩沖是對應所有數據文件中的一些被使用到的數據塊。讓他們能夠在內存中進行操作。在這個級別里沒有系統文件,,戶數據文件,臨時數據文件,回滾段文件之分。也就是任何文件的數據塊都有可能被緩沖。資料庫的任何修改都在該緩沖里完成,並由DBWR進程將修改後的數據寫入磁碟。

這個緩沖區的塊基本上在兩個不同的列表中管理。一個是塊的「臟」表(Dirty List),需要用資料庫塊的

書寫器(DBWR)來寫入,另外一個是不臟的塊的列表(Free List),一般的情況下,是使用最近最少使用 (Least Recently Used,LRU)演算法來管理。塊緩沖區高速緩存又可以細分為以下三個部分(Default pool,Keep pool,Recycle pool)。如果不是人為設置初始化參數(Init.ora),Oracle將默認為Default pool。由於操作系統定址能力的限制,不通過特殊設置,在32位的系統上,塊緩沖區高速緩存最大可以達到1.7G,在64位系統上,塊緩沖區高速緩存最大可以達到10G。

c、重做日誌緩沖區(Redo log buffer)

重做日誌文件的緩沖區,對資料庫的任何修改都按順序被記錄在該緩沖,然後由LGWR進程將它寫入磁碟。這些修改信息可能是DML語句,如(Insert,Update,Delete),或DDL語句,如(Create,Alter,Drop等)。 重做日誌緩沖區的存在是因為內存到內存的操作比較內存到硬碟的速度快很多,所以重作日誌緩沖區可以加快資料庫的操作速度,但是考慮的資料庫的一致性與可恢復性,數據在重做日誌緩沖區中的滯留時間不會很長。所以重作日誌緩沖區一般都很小,大於3M之後的重作日誌緩沖區已經沒有太大的實際意義。

d、Java程序緩沖區(Java Pool)

Java 的程序區,Oracle 8I 以後,Oracle 在內核中加入了對Java的支持。該程序緩沖區就是為Java 程序保留的。如果不用Java程序沒有必要改變該緩沖區的默認大小。

e、大池(Large Pool)

大池的得名不是因為大,而是因為它用來分配大塊的內存,處理比共享池更大的內存,在8.0開始引入。

下面對象使用大池:

MTS――在SGA的Large Pool中分配UGA

語句的並行查詢(Parallel Executeion of Statements)――允許進程間消息緩沖區的分配,用來協調 並行查詢伺服器

備份(Backup)――用於RMAN磁碟I/O緩存

4、後台進程(Background process)

後台進程是Oracle的程序,用來管理資料庫的讀寫,恢復和監視等工作。Server Process主要是通過他和user process進行聯系和溝通,並由他和user process進行數據的交換。在Unix機器上,Oracle後台進程相對於操作系統進程,也就是說,一個Oracle後台進程將啟動一個操作系統進程;在Windows機器上, Oracle後台進程相對於操作系統線程,打開任務管理器,我們只能看到一個Oracle.EXE的進程,但是通過另外的工具,就可以看到包含在這里進程中的線程。

在Unix上可以通過如下方法查看後台進程:

ps ?ef | grep ora_
# ps -ef | grep ora_ | grep XCLUAT
Oracle 29431 1 0 Sep 02 2:02 ora_dbwr_SID
Oracle 29444 1 0 Sep 02 0:03 ora_ckpt_SID
Oracle 29448 1 0 Sep 02 2:42 ora_smon_SID
Oracle 29442 1 0 Sep 02 3:25 ora_lgwr_SID
Oracle 29427 1 0 Sep 02 0:01 ora_pmon_SID

a、Oracle系統有5 個基本進程他們是
DBWR(數據文件寫入進程)
LGWR(日誌文件寫入進程)
SMON(系統監護進程)
PMON(用戶進程監護進程)
CKPT(檢查點進程,同步數據文件, 日誌文件,控制文件)

b、DBWR
將修改過的數據緩沖區的數據寫入對應數據文件
維護系統內的空緩沖區
這里指出幾個容易錯誤的概念:
當一個更新提交後,DBWR把數據寫到磁碟並返回給用戶提交完成.
DBWR會觸發CKPT 後台進程
DBWR不會觸發LGWR 進程
上面的概念都是錯誤的.
DBWR是一個很底層的工作進程,他批量的把緩沖區的數據寫入磁碟。和任何前台用戶的進程幾乎沒有什麼關系,也不受他們的控制。至於DBWR會不會觸發LGWR和CKPT進程,我們將在下面幾節里討論。
DBWR工作的主要條件如下
DBWR 超時
系統中沒有多的空緩沖區用來存放數據
CKPT 進程觸發DBWR 等

c、LGWR
將重做日誌緩沖區的數據寫入重做日誌文件,LGWR是一個必須和前台用戶進程通信的進程。當數據被修改的時候,系統會產生一個重做日誌並記錄在重做日誌緩沖區內。這個重做日誌可以類似的認為是以下的一個結構:
SCN=000000001000
數據塊ID
對象ID=0801
數據行=02
修改後的數據=0011
提交的時候,LGWR必須將被修改的數據的重做日誌緩沖區內數據寫入日誌數據文件,然後再通知前台進程提交成功,並由前台進程通知用戶。從這點可以看出LGWR承擔了維護系統數據完整性的任務。
LGWR 工作的主要條件如下
用戶提交
有1/3 重做日誌緩沖區未被寫入磁碟
有大於1M 重做日誌緩沖區未被寫入磁碟
超時
DBWR需要寫入的數據的SCN號大於LGWR 記錄的SCN號,DBWR 觸發LGWR寫入

d、SMON
工作主要包含
清除臨時空間
在系統啟動時,完成系統實例恢復
聚結空閑空間
從不可用的文件中恢復事務的活動
OPS中失敗節點的實例恢復
清除OBJ$表
縮減回滾段
使回滾段離線

e、PMON
主要用於清除失效的用戶進程,釋放用戶進程所用的資源。如PMON將回滾未提交的工作,釋放鎖,釋放分配給失敗進程的SGA資源。

f、CKPT
同步數據文件,日誌文件和控制文件,由於DBWR/LGWR的工作原理,造成了數據文件,日誌文件,控制文件的不一至,這就需要CKPT進程來同步。CKPT會更新數據文件/控制文件的頭信息。
CKPT工作的主要條件如下
在日誌切換的時候
資料庫用immediate ,transaction , normal 選項shutdown 資料庫的時候
根據初始話文件LOG_CHECKPOINT_INTERVAL、LOG_CHECKPOINT_TIMEOUT、FAST_START_IO_TARGET 的設置的數值來確定
用戶觸發
以下進程的啟動需要手工配置

g、ARCH
當資料庫以歸檔方式運行的時候,Oracle會啟動ARCH進程,當重做日誌文件被寫滿時,日誌文件進行切換,舊的重做日誌文件就被ARCH進程復制到一個/多個特定的目錄/遠程機器。這些被復制的重做日誌文件被叫做歸檔日誌文件。

h、RECO
負責解決分布事物中的故障。Oracle可以連接遠程的多個資料庫,當由於網路問題,有些事物處於懸而未決的狀態。RECO進程試圖建立與遠程伺服器的通信,當故障消除後,RECO進程自動解決所有懸而未決的會話。
i、服務進程Server Process
服務進程的分類
專用服務進程(Dedicated Server Process)
一個服務進程對應一個用戶進程
共享服務進程(MultiTreaded Server Process)
一個服務進程對應多個用戶進程,輪流為用戶進程服務。
PGA & UGA
PGA = Process Global Area
UGA = User Global Area
他保存了用戶的變數、許可權、堆棧、排序空間等用戶信息,對於專用伺服器進程,UGA在PGA中分配。對於多線程進程,UGA在Large pool中分配。

j、用戶進程User Process
在客戶端,將用戶的SQL 語句傳遞給服務進程

5、一個貫穿資料庫全局的概念----系統改變號SCN(System Change Number)
系統改變號,一個由系統內部維護的序列號。當系統需要更新的時候自動增加,他是系統中維持數據的一致性和順序恢復的重要標志。

a. 查詢語句不會使SCN增加,就算是同時發生的更新,資料庫內部對應的SCN也是不同的。這樣一來就保證了數據恢復時候的順序。

b. 維持數據的一致性,當一

二、Oracle 資料庫

Oracle資料庫的組成――物理操作系統文件的集合。主要包括以下幾種。

1、控制文件(參數文件init.ora記錄了控制文件的位置)
控制文件包括如下主要信息
資料庫的名字,檢查點信息,資料庫創建的時間戳
所有的數據文件,聯機日誌文件,歸檔日誌文件信息
備份信息等
有了這些信息,Oracle就知道那些文件是數據文件,現在的重做日誌文件是哪些,這些都是系統啟動和運行的基本條件,所以他是Oracle運行的根本。如果沒有控制文件系統是不可能啟動的。控制文件是非常重要的,一般採用多個鏡相復制來保護控制文件,或採用RAID來保護控制文件。控制文件的丟失,將使資料庫的恢復變的很復雜。
控制文件信息可以從V$Controlfile中查詢獲得

2、數據文件(數據文件的詳細信息記載在控制文件中)
可以通過如下方式查看數據文件
SQL> select name from v$datafile;
NAME
---------------------------------------------
/u05/dbf/PROD/system_01.dbf
/u06/dbf/PROD/temp_01.dbf
/u04/dbf/PROD/users_01.dbf
/u09/dbf/PROD/rbs_01.dbf
/u06/dbf/PROD/applsys_indx_01.dbf
/u05/dbf/PROD/applsys_data_01.dbf
從以上可以看出,數據文件大致可以分為以下幾類:

i. 系統數據文件(system_01.dbf)
存放系統表和數據字典,一般不放用戶的數據,但是用戶腳本,如過程,函數,包等卻是保存在數據字典中的。
名詞解釋:數據字典 數據字典是一些系統表或視圖,他存放系統的信息,他包括資料庫版本,數據文件信息,表與索引等段信息,系統的運行狀態等各種和系統有關的信息和用戶腳本信息。資料庫管理員可以通過對數據字典的查詢,就可以了解到Oracle的運行狀態。

ii. 回滾段文件(rbs_01.dbf)
如果資料庫進行對數據的修改,那麼就必須使用回滾段,回滾段是用來臨時存放修改前的數據(Before Image)。回滾段通常都放在一個單獨的表空間上(回滾表空間),避免表空間碎片化,這個表空間包含的數據文件就是回滾數據文件。

iii. 臨時數據文件(temp_01.dbf)
主要存放用戶的排序等臨時數據,與回滾段相似,臨時段也容易引起表空間碎片化,而且沒有辦法在一個永久表空間上開辟臨時段,所以就必須有一個臨時表空間,它所包含的數據文件就是臨時數據文件,主要用於不能在內存上進行的排序操作。我們必須為用戶指定一個臨時表空間。

iv. 用戶數據文件(/applsys_data_01.dbf ,applsys_indx_01.dbf)
存放用戶數據,這里列舉了兩類常見的用戶型數據,一般數據和索引數據,一般來說,如果條件許可的話,可以考慮放在不同的磁碟上。

3、重做日誌文件(聯機重做日誌)
用戶對資料庫進行的任何操作都會記錄在重做日誌文件。在了解重做日誌之前必須了解重做日誌的兩個概念,重做日誌組和重做日誌組成員(Member),一個資料庫中至少要有兩個日誌組文件,一組寫完後再寫另一組,即輪流寫。每個日誌組中至少有一個日誌成員,一個日誌組中的多個日誌成員是鏡相關系,有利於日誌文件的保護,因為日誌文件的損壞,特別是當前聯機日誌的損壞,對資料庫的影響是巨大的。
聯機日誌組的交換過程叫做切換,需要特別注意的是,日誌切換在一個優化效果不好的資料庫中會引起臨時的「掛起」。掛起大致有兩種情況:
在歸檔情況下,需要歸檔的日誌來不及歸檔,而聯機日誌又需要被重新利用
檢查點事件還沒有完成(日誌切換引起檢查點),而聯機日誌需要被重新利用
解決這種問題的常用手段是:

i.增加日誌組

ii.增大日誌文件成員大小
通過v$log可以查看日誌組,v$logfile可以查看具體的成員文件。

4、歸檔日誌文件
Oracle可以運行在兩種模式之中,歸檔模式和不歸檔模式。如果不用歸檔模式,當然,你就不會有歸檔日誌,但是,你的系統將不會是一個實用系統,特別是不能用於生產系統,因為你可能會丟失數據。但是在歸檔模式中,為了保存用戶的所有修改,在重做日誌文件切換後和被覆蓋之間系統將他們另外保存成一組連續的文件系列,該文件系列就是歸檔日誌文件。
有人或許會說,歸檔日誌文件佔領我大量的硬碟空間,其實,具體想一想,你是願意浪費一點磁碟空間來保護你的數據,還是願意丟失你的數據呢?顯而義見,我們需要保證我們的數據的安全性。其實,歸檔並不是一直佔領你的磁碟空間,你可以把她備份到磁帶上,或則刪除上一次完整備份前的所有日誌文件。

5、初始化參數文件
initSID.ora或init.ora文件,因為版本的不一樣,其位置也可能會不一樣。在8i中,通常位於$Oracle_HOME/admin//Pfile下,初始化文件記載了許多資料庫的啟動參數,如內存,控制文件,進程數等,在資料庫啟動的時候載入(Nomount時載入),初始化文件記錄了很多重要參數,對資料庫的性能影響很大,如果不是很了解,不要輕易亂改寫,否則會引起資料庫性能下降。

6、其他文件
i . 密碼文件
用於Oracle 的具有sysdba許可權用戶的認證.
ii. 日誌文件
報警日誌文件(alert.log或alrt.ora)
記錄資料庫啟動,關閉和一些重要的出錯信息。資料庫管理員應該經常檢查這個文件,並對出現的問題作出即使的反應。你可以通過以下SQL 找到他的路徑select value from v$PARAMETER where name ="background_mp_dest";
後台或用戶跟蹤文件
系統進程或用戶進程出錯前寫入的信息,一般不可能讀懂,可以通過Oracle的TKPROF工具轉化為可以讀懂的格式。對於系統進程產生的跟蹤文件與報警日誌文件的路徑一樣,用戶跟蹤文件的路徑,你可以通過以下SQL找到他的路徑select value from v$PARAMETER where name ="user_mp_dest";

三、Oracle邏輯結構

1、 表空間(tablespace)
表空間是資料庫中的基本邏輯結構,一系列數據文件的集合。一個表空間可以包含多個數據文件,但是一個數據文件只能屬於一個表空間。

2、 段(Segment)
段是對象在資料庫中佔用的空間,雖然段和資料庫對象是一一對應的,但段是從資料庫存儲的角度來看的。一個段只能屬於一個表空間,當然一個表空間可以有多個段。
表空間和數據文件是物理存儲上的一對多的關系,表空間和段是邏輯存儲上的一對多的關系,段不直接和數據文件發生關系。一個段可以屬於多個數據文件,關於段可以指定擴展到哪個數據文件上面。
段基本可以分為以下四種
數據段(Data Segment)
索引段(Index Segment)
回滾段(Rollback Segment)
臨時段(Temporary Segment)

3、區間(Extent)
關於Extent的翻譯有多種解釋,有的譯作擴展,有的譯作盤區,我這里通常譯為區間。在一個段中可以存在多個區間,區間是為數據一次性預留的一個較大的存儲空間,直到那個區間被用滿,資料庫會繼續申請一個新的預留存儲空間,即新的區間,一直到段的最大區間數(Max Extent)或沒有可用的磁碟空間可以申請。 在Oracle8i以上版本,理論上一個段可以無窮個區間,但是多個區間對Oracle卻是有性能影響的,Oracle建議把數據分布在盡量少的區間上,以減少Oracle的管理與磁頭的移動。

4、Oracle數據塊(Block)
Oracle最基本的存儲單位,他是OS數據塊的整數倍。Oracle的操作都是以塊為基本單位,一個區間可以包含多個塊(如果區間大小不是塊大小的整數倍,Oracle實際也擴展到塊的整數倍)。

5、基本表空間介紹

a. 系統表空間
主要存放數據字典和內部系統表基表
查看數據數據字典的SQL
select * from dict
查看內部系統表的SQL
select * from v$fixed_view_definition
DBA對系統的系統表中的數據字典必須有一個很深刻的了解,他們必須准備一些基礎的SQL語句,通過這些SQL可以立即了解系統的狀況和資料庫的狀態,這些基本的SQL包括
系統的剩餘空間
系統的SGA
狀態系統的等待
用戶的許可權
當前的用戶鎖
緩沖區的使用狀況等
在成為DBA 的道路上我們不建議你過分的依賴於OEM/Quest 等優秀的資料庫管理工具,因為他們不利於你對數據數據字典的理解,SQL語句可以完成幾乎全部的資料庫管理工作。
大量的讀少量的寫是該表空間的一個顯著的特點。

b. 臨時表空間.
臨時表空間顧名思義是用來存放臨時數據的,例如排序操作的臨時空間,他的空間會在下次系統啟動的時候全部被釋放。

c. 回滾段表空間

i. 回滾段在系統中的作用
當資料庫進行更新插入刪除等操作的時候,新的數據被更新到原來的數據文件,而舊的數據(Before Image)就被放到回滾段中,如果數據需要回滾,那麼可以從回滾段將數據再復制到數據文件中。來完成數據的回滾。在系統恢復的時候, 回滾段可以用來回滾沒有被commit 的數據,解決系統的一至性。
回滾段在什麼情況下都是大量的寫,一般是少量讀,因此建議把回滾段單獨出來放在一個單獨的設備(如單獨的磁碟或RAID),以減少磁碟的IO爭用。

ii. 回滾段的工作方式
一個回滾表空間可以被劃分成多個回滾段.
一個回滾段可以保存多個會話的數據.
回滾段是一個圓形的數據模型
假設回滾段由4 個區間組成,他們的使用順序就是區間1à區間2à區間3à區間4à區間1。也就是說,區間是可以循環使用的,當區間4到區間1的時候,區間1裡面的會話還沒有結束, 區間4用完後就不能再用區間1,這時系統必須分配區間5,來繼續為其他會話服務服務。
我們分析一個Update 語句的完成

①. 用戶提交一個Update 語句

②. Server Process 檢查內存緩沖.
如果沒有該數據塊的緩沖,則從磁碟讀入

i. 如果沒有內存的有效空間,DBWR被啟動將未寫入磁碟的臟緩沖寫入磁碟

ii. 如果有有效空間,則讀入

③. 在緩沖內更新數據

i. 申請一個回滾段入口,將舊數據寫如回滾段

ii. 加鎖並更新數據

iii. 並在同時將修改記錄在Redo log buffer中

『叄』 redis 怎麼緩存用戶列表,做到可以分頁展示

redis是類似key_value形式的快速緩存服務。類型較豐富,可以保存對象、列表等,支持的操作也很豐富,屬於內存資料庫,且可以把內存中的數據及時或定時的寫入到磁碟。可設置過期自動刪除,速度快,易於使用。

『肆』 python導入模塊或包需要注意哪些點

Python是一種面向對象的編程語言,裡麵包含有豐富強大的庫,想要學習Python開發,首先需要學習如何導入模塊或包。下面就跟大家一起討論下Python導入模塊的幾種方法:
常規導入
最常用的導入方式,大概是這樣的:
import sys
只需要使用 import ,然後指定希望導入的模塊或包即可。用這種方法導入的好處是可以一次性導入多個包或模塊:
import os, sys, time
雖然這節省了空間,但是卻違背了Python風格指南。 Python風格指南建議將每個導入語句單獨成行 。
有時在導入模塊時,你想要重命名這個模塊。這個功能很容易實現:
import sys as system
print(system.platform)
上面的代碼將我們導入的 sys 模塊重命名為 system 。我們可以按照和以前一樣的方式調用模塊的方法,但是可以用一個新的模塊名。也有某些子模塊必須要使用點標記法才能導入。
import urllib.error
這個情況不常見,但是對此有所了解總是沒有壞處的。
使用from語句導入
有時我們只想要導入一個模塊或庫中的某個部分。那麼Python是如何實現這點:
from functools import lru_cache
上面這行代碼可以讓你直接調用 lru_cache 。如果按常規方式導入 functools ,那麼就必須像這樣調用 lru_cache :
functools.lru_cache(*args)
根據實際的使用場景,上面的做法可能是更好的。在復雜的代碼庫中,能夠看出某個函數是從哪裡導入的這點很有用的。不過,如果你的代碼維護的很好,模塊化程度高,那麼只從某個模塊中導入一部分內容也是非常方便和簡潔的。
當然,你還可以使用from方法導入模塊的全部內容,就像這樣:
from os import *
這種做法在少數情況下是挺方便的,但是這樣也會打亂你的命名空間。問題在於,你可能定義了一個與導入模塊中名稱相同的變數或函數,這時如果你試圖使用
os 模塊中的同名變數或函數,實際使用的將是你自己定義的內容。因此,你最後可能會碰到一個相當讓人困惑的邏輯錯誤。
標准庫中我唯一推薦全盤導入的模塊只有Tkinter 。
如果你正好要寫自己的模塊或包,有人會建議你在 __init__.py 文件中導入所有內容,讓模塊或者包使用起來更方便。我個人更喜歡顯示地導入,而非隱式地導入。
你也可以採取折中方案,從一個包中導入多個項:
from os import path, walk, unlinkfrom os import uname, remove
在上述代碼中,我們從 os 模塊中導入了5個函數。你可能注意到了,我們是通過多次從同一個模塊中導入實現的。當然,如果你願意的話,你也可以使用圓括弧一次性導入多個項:
from os import (path, walk, unlink, uname,
remove, rename)
這是一個有用的技巧,不過你也可以換一種方式:
from os import path, walk, unlink, uname, \
remove, rename
上面的反斜杠是Python中的續行符,告訴解釋器這行代碼延續至下一行。
相對導入
PEP 328 介紹了引入相對導入的原因,以及選擇了哪種語法。具體來說,是使用句點來決定如何相對導入其他包或模塊。這么做的原因是為了避免偶然情況下導入標准庫中的模塊產生沖突。這里我們以PEP 328中給出的文件夾結構為例,看看相對導入是如何工作的:
my_package/
__init__.py
subpackage1/
__init__.py
mole_x.py
mole_y.py
subpackage2/
__init__.py
mole_z.py
mole_a.py
在本地磁碟上找個地方創建上述文件和文件夾。在頂層的 __init__.py 文件中,輸入以下代碼:
from . import subpackage1from . import subpackage2
接下來進入 subpackage1 文件夾,編輯其中的 __init__.py 文件,輸入以下代碼:
from . import mole_xfrom . import mole_y
現在編輯 mole_x.py 文件,輸入以下代碼:
from .mole_y import spam as ham
def main():
ham()
最後編輯 mole_y.py 文件,輸入以下代碼:
def spam():
print('spam ' * 3)
打開終端, cd 至 my_package 包所在的文件夾,但不要進入 my_package 。在這個文件夾下運行Python解釋器。我使用的是IPython,因為它的自動補全功能非常方便:
In [1]: import my_package
In [2]: my_package.subpackage1.mole_xOut[2]: <mole
'my_package.subpackage1.mole_x' from
'my_package/subpackage1/mole_x.py'>
In [3]: my_package.subpackage1.mole_x.main()spam spam spam
相對導入適用於你最終要放入包中的代碼。如果你編寫了很多相關性強的代碼,那麼應該採用這種導入方式。
你會發現PyPI上有很多流行的包也是採用了相對導入 。還要注意一點,如果你想要跨越多個文件層級進行導入,只需要使用多個句點即可。不過, PEP
328建議相對導入的層級不要超過兩層 。
還要注意一點,如果你往 mole_x.py 文件中添加了 if __name__ == 『__main__』 ,然後試圖運行這個文件,你會碰到一個很難理解的錯誤。編輯一下文件,試試看吧!
from . mole_y import spam as ham
def main():
ham()
if __name__ == '__main__':
# This won't work!
main()
現在從終端進入 subpackage1 文件夾,執行以下命令:
python mole_x.py
如果你使用的是Python 2,你應該會看到下面的錯誤信息:
Traceback (most recent call last):
File "mole_x.py", line 1, in <mole>
from . mole_y import spam as hamValueError: Attempted relative import in non-package
如果你使用的是Python 3,錯誤信息大概是這樣的:
Traceback (most recent call last):
File "mole_x.py", line 1, in <mole>
from . mole_y import spam as hamSystemError: Parent mole '' not loaded, cannot perform relative import
這指的是, mole_x.py 是某個包中的一個模塊,而你試圖以腳本模式執行,但是 這種模式不支持相對導入 。
如果你想在自己的代碼中使用這個模塊,那麼你必須將其添加至Python的導入檢索路徑(import search path)。最簡單的做法如下:
import syssys.path.append('/path/to/folder/containing/my_package')import my_package
注意,你需要添加的是 my_package 的上一層文件夾路徑,而不是 my_package 本身。原因是 my_package 就是我們想要使用的包,所以如果你添加它的路徑,那麼將無法使用這個包。
我們接下來談談可選導入。
可選導入(Optional imports)
如果你希望優先使用某個模塊或包,但是同時也想在沒有這個模塊或包的情況下有備選,你就可以使用可選導入這種方式。這樣做可以導入支持某個軟體的多種版本或者實現性能提升。以 github2包 中的代碼為例:
try:
# For Python 3
from http.client import responsesexcept ImportError: # For Python 2.5-2.7
try:
from httplib import responses # NOQA
except ImportError: # For Python 2.4
from BaseHTTPServer import BaseHTTPRequestHandler as _BHRH
responses = dict([(k, v[0]) for k, v in _BHRH.responses.items()])
lxml 包也有使用可選導入方式:
try:
from urlparse import urljoin
from urllib2 import urlopenexcept ImportError:
# Python 3
from urllib.parse import urljoin
from urllib.request import urlopen
正如以上示例所示, 可選導入的使用很常見,是一個值得掌握的技巧 。
局部導入
當你在局部作用域中導入模塊時,你執行的就是局部導入。如果你在Python腳本文件的頂部導入一個模塊,那麼你就是在將該模塊導入至全局作用域,這意味著之後的任何函數或方法都可能訪問該模塊。例如:
import sys # global scope
def square_root(a):
# This import is into the square_root functions local scope
import math
return math.sqrt(a)
def my_pow(base_num, power):
return math.pow(base_num, power)
if __name__ == '__main__':
print(square_root(49))
print(my_pow(2, 3))
這里,我們將 sys 模塊導入至全局作用域,但我們並沒有使用這個模塊。然後,在 square_root 函數中,我們將 math
模塊導入至該函數的局部作用域,這意味著 math 模塊只能在 square_root 函數內部使用。如果我們試圖在 my_pow 函數中使用
math ,會引發 NameError 。試著執行這個腳本,看看會發生什麼。
使用局部作用域的好處之一,是你使用的模塊可能需要很長時間才能導入,如果是這樣的話,將其放在某個不經常調用的函數中或許更加合理,而不是直接在全局作
用域中導入。老實說,我幾乎從沒有使用過局部導入,主要是因為如果模塊內部到處都有導入語句,會很難分辨出這樣做的原因和用途。
根據約定,所有的導入語句都應該位於模塊的頂部 。
導入注意事項
在導入模塊方面,有幾個程序員常犯的錯誤。這里我們介紹兩個。
循環導入(circular imports)
覆蓋導入(Shadowed imports,暫時翻譯為覆蓋導入)
先來看看循環導入。
循環導入
如果你創建兩個模塊,二者相互導入對方,那麼就會出現循環導入。例如:
# a.pyimport b
def a_test():
print("in a_test")
b.b_test()
a_test()
然後在同個文件夾中創建另一個模塊,將其命名為 b.py 。
import a
def b_test():
print('In test_b"')
a.a_test()
b_test()
如果你運行任意一個模塊,都會引發 AttributeError 。這是因為這兩個模塊都在試圖導入對方。簡單來說,模塊 a 想要導入模塊 b
,但是因為模塊 b 也在試圖導入模塊 a (這時正在執行),模塊 a 將無法完成模塊 b
的導入。我看過一些解決這個問題的破解方法(hack),但是 一般來說,你應該做的是重構代碼,避免發生這種情況 。
覆蓋導入
當你創建的模塊與標准庫中的模塊同名時,如果你導入這個模塊,就會出現覆蓋導入。舉個例子,創建一個名叫 math.py 的文件,在其中寫入如下代碼:
import math
def square_root(number):
return math.sqrt(number)
square_root(72)
現在打開終端,試著運行這個文件,你會得到以下回溯信息(traceback):
Traceback (most recent call last):
File "math.py", line 1, in <mole>
import math
File "/Users/michael/Desktop/math.py", line 6, in <mole>
square_root(72)
File "/Users/michael/Desktop/math.py", line 4, in square_root
return math.sqrt(number)AttributeError: mole 'math' has no attribute 'sqrt'
這到底是怎麼回事?其實,你運行這個文件的時候,Python解釋器首先在當前運行腳本所處的的文件夾中查找名叫 math
的模塊。在這個例子中,解釋器找到了我們正在執行的模塊,試圖導入它。但是我們的模塊中並沒有叫 sqrt 的函數或屬性,所以就拋出了
AttributeError 。

『伍』 android okhttp超時怎麼辦

OkHttp是一個在開發可汗學院AndroidAPP過程中非常重要的依賴庫。它的默認的配置為我們提供了非常重要實用功能,下面一些步驟我們可以讓Okhttp提供功能使用靈活和內省能力。1.啟用文件系統上的響應緩存默認情況下,Okhttp不支持響應緩存,包括HTTPCache-Control頭允許緩存響應。因此,客戶端通過一次又一次的請求相同的資源浪費時間和帶寬。而不是簡單地讀取初始響應後緩存的副本。要在文件系統中啟用響應緩存,需要配置com.squareup.okhttp.Cache實例,並把它傳遞給你的OkHttpClient實例的setCache方法。你必須初始化緩存與存放目錄的文件,並以位元組為單位的最大值。響應返回數據可以寫入給定目錄文件,如果一個響應的緩存超過了給定的大小。我們可以採取LRUpolicy。我們可以在stackoverflow查看JesseWilson的回復。我們可以通過context.getCacheDir()在子目錄中緩存我們的響應://Basedirectoryrecommendedby/q/4441849/400717.final@NullableFilebaseDir=context.getCacheDir();if(baseDir!=null){finalFilecacheDir=newFile(baseDir,"HttpResponseCache");okHttpClient.setCache(newCache(cacheDir,HTTP_RESPONSE_DISK_CACHE_MAX_SIZE));}//Basedirectoryrecommendedby/q/4441849/400717.final@NullableFilebaseDir=context.getCacheDir();if(baseDir!=null){finalFilecacheDir=newFile(baseDir,"HttpResponseCache");okHttpClient.setCache(newCache(cacheDir,HTTP_RESPONSE_DISK_CACHE_MAX_SIZE));}在可汗學院的程序中我們指定HTTP_RESPONSE_DISK_CACHE_MAX_SIZEas10*1024*1024,or10MB的大小2.集成StethoStetho是Facebook的一個可愛的庫,可以使用Chrome瀏覽器的Chrome開發人員工具功能來檢查你的Android應用程序。Stetho除了允許你檢查你的應用程序的SQLite資料庫,還可以查看View的層次結構。允許你檢查由OkHttp發起的每個請求和響應:這種自省機制是確保伺服器返回允許資源緩存的HTTP頭是非常有用的,以及驗證沒有請求時,保證緩存的資源存在。要想使用Stetho,只需添加一個StethoInterceptor實例的網路攔截器列表:okHttpClient.networkInterceptors().add(newStethoInterceptor());okHttpClient.networkInterceptors().add(newStethoInterceptor());然後,運行應用程序,打開瀏覽器後,輸入chrome://inspect。然後你就會看到應用程序的設備和標識符的列表。然後滑鼠右鍵選擇inspect打開開發者工具,然後打開新的tab,開始監控OkHttp請求。3.使用Picasso和Retrofit你可能使用過Picasso來載入網路圖片,或者使用Retrofit來簡化發出請求和解碼響應。這些第三方庫將隱式地創建自己的OkHttpClient供內部使用,如果你不明確指定一個。Picassoversion2.5.2的OkHttpDownloader類:(){OkHttpClientclient=newOkHttpClient();client.setConnectTimeout(Utils.DEFAULT_CONNECT_TIMEOUT_MILLIS,TimeUnit.MILLISECONDS);client.setReadTimeout(Utils.DEFAULT_READ_TIMEOUT_MILLIS,TimeUnit.MILLISECONDS);client.setWriteTimeout(Utils.DEFAULT_WRITE_TIMEOUT_MILLIS,TimeUnit.MILLISECONDS);returnclient;}(){OkHttpClientclient=newOkHttpClient();client.setConnectTimeout(Utils.DEFAULT_CONNECT_TIMEOUT_MILLIS,TimeUnit.MILLISECONDS);client.setReadTimeout(Utils.DEFAULT_READ_TIMEOUT_MILLIS,TimeUnit.MILLISECONDS);client.setWriteTimeout(Utils.DEFAULT_WRITE_TIMEOUT_MILLIS,TimeUnit.MILLISECONDS);returnclient;}Retrofit也有類似的工廠方法來創建自己的OkHttpClient。圖片一般在應用程序中需要載入的比較大的資源。盡管Picasso自己維護它的LRU機制來緩存圖片,在內存中嚴格執行。如果客戶端嘗試使用Picasso來載入圖片。Picasso會找不到其在內存中緩存圖像,然後將委託載入該圖片到它的內部OkHttpClient實例。並且默認情況下該實例將始終從伺服器載入圖片資源。作為defaultOkHttpClient的方法不能與上面提到的文件系統中的響應緩存配置結合起來。指定你自己的OkHttpClient實例允許返回數據從文件系統緩存響應,圖片不會從伺服器載入。這是非常重要的在程序第一次啟動以後。這個時候Picasso的內存緩存是冷的。所以它會頻繁的委託OkHttpClient實例去載入圖片。這就需要構建配置了您Picasso的OkHttpClient實例,如果你在你的代碼中使用Picasso.with(context).load()Picasso.with(context).load()載入圖片,你是用的是Picasso的單例模式。這是通過with方法懶漢模式地實例化並配置自己的OkHttpClient。因此,我們必須使我們自己的Picasso實例在單例之前通過wiht方法調用。實現這個,可以簡單的將OkHttpClient實例封裝在OkHttpDownloader中,然後傳遞給Picasso.Builder實例的downloader方法。finalPicassopicasso=newPicasso.Builder(context).downloader(newOkHttpDownloader(okHttpClient)).build();//,butreplacethesingleton//instancejustincase.Picasso.setSingletonInstance(picasso);finalPicassopicasso=newPicasso.Builder(context).downloader(newOkHttpDownloader(okHttpClient)).build();//,butreplacethesingleton//instancejustincase.Picasso.setSingletonInstance(picasso);在Retrofit中要使用OkHttpClient實例,需要改造1.9.x的一個RestAdapter,需要將OkHttpClient封裝OkClient的實例中。然後把它傳遞給RestAdapter.Builder實例的setClient方法。restAdapterBuilder.setClient(newOkClient(httpClient));restAdapterBuilder.setClient(newOkClient(httpClient));在Retrofit2.0中只需要簡單的將OkHttpClient傳遞給Retrofit.Builder實例的client方法。在可汗學院的APP中我們通過Dagger依賴注入來確保我們只有一個OkHttpClient的實例。這種方法同樣也適用於Picasso和Retrofit我們提供了一個為OkHttpClient實例提供單例模式的註解示例:@Provides@(finalContextcontext,){finalOkHttpClientokHttpClient=newOkHttpClient();configureClient(okHttpClient,);returnokHttpClient;}@Provides@(finalContextcontext,){finalOkHttpClientokHttpClient=newOkHttpClient();configureClient(okHttpClient,);returnokHttpClient;}OkHttpClient將會通過Dagger的註解創建一個實例提供給我們的Picasso和Retrofit。4.指定一個用戶代理攔截器日誌文件和分析為我們提供了有用的信息,當客戶在每個請求提供詳細的User-Agentheader值的時候。默認情況下,Okhttp包含User-Agent值只有在特定的Okhttp版本中。為了指定我們自己的useragent。首先創建攔截器的替換值,我們可以看stackoverflow的建議。{privatestaticfinalStringUSER_AGENT_HEADER_NAME="User-Agent";;publicUserAgentInterceptor(StringuserAgentHeaderValue){this.userAgentHeaderValue=Preconditions.checkNotNull(userAgentHeaderValue);}@(Chainchain)throwsIOException{finalRequestoriginalRequest=chain.request();=originalRequest.newBuilder().removeHeader(USER_AGENT_HEADER_NAME).addHeader(USER_AGENT_HEADER_NAME,userAgentHeaderValue).build();returnchain.proceed(requestWithUserAgent);}}{privatestaticfinalStringUSER_AGENT_HEADER_NAME="User-Agent";;publicUserAgentInterceptor(StringuserAgentHeaderValue){this.userAgentHeaderValue=Preconditions.checkNotNull(userAgentHeaderValue);}@(Chainchain)throwsIOException{finalRequestoriginalRequest=chain.request();=originalRequest.newBuilder().removeHeader(USER_AGENT_HEADER_NAME).addHeader(USER_AGENT_HEADER_NAME,userAgentHeaderValue).build();returnchain.proceed(requestWithUserAgent);}}為了創建User-Agentheader值人然後傳遞給UserAgentInterceptor的構造器,使用你得到的任何信息。我們可以使用:android的系統信息可以清晰的傳遞出這是一台android設備Build.MODEL或者「製造商提供的用戶可見最終可見的名稱」Build.BRAND或者「消費者可見的品牌與產品/硬體相關信息」Build.VERSION.SDK_INT或者「消費者可見的Android提供的SDK版本號」BuildConfig.APPLICATION_IDBuildConfig.VERSION_NAMEBuildConfig.VERSION_CODE最後三個值由的applicationID,VERSIONCODE和VERSIONNAME的值在我們的Gradlebuild腳本中了解信息可以查看versioningyourapplications和請注意,如果您的應用程序使用的是WebView,您可以配置使用相同的User-Agentheader值,你可以通過下面方法創建UserAgentInterceptor:WebSettingssettings=webView.getSettings();settings.setUserAgentString(userAgentHeaderValue);WebSettingssettings=webView.getSettings();settings.setUserAgentString(userAgentHeaderValue);5.指定合理的超時2.5.0版本之前,OkHttp請求默認為永不超時。2.5.0版本開始如果建立連接請求超時,如果從連接讀取下一個位元組或寫入的下一個位元組到連接,花費超過10秒,就終止。這樣做需要更新到2.5.0版本我們就不需要在我們的代碼中修改bug。原因很簡單是我因為我們第一次使用的時候使用了錯誤的路徑。要覆蓋這些默認值,可以分別調用setConnectTimeout,setReadTimeout或setWriteTimeout。需要注意的是Picasso和Retrofit為OkHttpClient實例指定不同的超時值時,默認情況下,Picasso指定:連接超過15秒.讀取超過20秒寫入超過20秒而Retrofit指定:連接超過15秒.讀取超過20秒沒有寫入超時通過配置Picasso和Retrofit自己的OkHttpClient實例你可以確保所有的請求超時是一致的

『陸』 redis內存滿了怎麼辦

redis內存滿了解決方法:

1,增加內存。

2,使用內存淘汰策略。

3,Redis集群。

重點介紹下2、3:

第二點:

我們知道,redis設置配置文件的maxmemory參數,可以控制其最大可用內存大小(位元組)。

那麼當所需內存,超過maxmemory怎麼辦?

這個時候就該配置文件中的maxmemory-policy出場了。

其默認值是noeviction。

下面我將列出當可用內存不足時,刪除redis鍵具有的淘汰規則。

規則說明:

1、volatile-lru

使用LRU演算法刪除一個鍵(只對設置了生存時間的鍵)

2、allkeys-lru

使用LRU演算法刪除一個鍵

3、volatile-random

隨機刪除一個鍵(只對設置了生存時間的鍵)

4、allkeys-random

隨機刪除一個鍵

5、volatile-ttl

刪除生存時間最近的一個鍵

6、noeviction

不刪除鍵,只返回錯誤

LRU演算法,least RecentlyUsed,最近最少使用演算法。也就是說默認刪除最近最少使用的鍵。

但是一定要注意一點!redis中並不會准確的刪除所有鍵中最近最少使用的鍵,而是隨機抽取3個鍵,刪除這三個鍵中最近最少使用的鍵。

那麼3這個數字也是可以設置的,對應位置是配置文件中的maxmeory-samples.

三、集群怎麼做

Redis僅支持單實例,內存一般最多10~20GB。對於內存動輒100~200GB的系統,就需要通過集群來支持了。

Redis集群有三種方式:客戶端分片、代理分片、RedisCluster(在之後一篇文章詳細說一下。)

1、客戶端分片

通過業務代碼自己實現路由

優勢:可以自己控制分片演算法、性能比代理的好

劣勢:維護成本高、擴容/縮容等運維操作都需要自己研發

2、代理分片

代理程序接收到來自業務程序的數據請求,根據路由規則,將這些請求分發給正確的Redis實例並返回給業務程序。使用類似Twemproxy、Codis等中間件實現。

優勢:運維方便、程序不用關心如何鏈接Redis實例

劣勢:會帶來性能消耗(大概20%)、無法平滑擴容/縮容,需要執行腳本遷移數據,不方便(Codis在Twemproxy基礎上優化並實現了預分片來達到Auto Rebalance)。

3、Redis Cluster

優勢:官方集群解決方案、無中心節點,和客戶端直連,性能較好

劣勢:方案太重、無法平滑擴容/縮容,需要執行相應的腳本,不方便、太新,沒有相應成熟的解決案例

『柒』 mysql有基於LRU緩沖池,其它輔助緩存如memcached和redis的意義應該就不需要了,還是有其它需要的理由

1、首先明確是不是一定要上緩存,當前架構的瓶頸在哪裡,若瓶頸真是資料庫操作上,再繼續往下看。
2、明確memcached和redis的區別,到底要使用哪個。前者終究是個緩存,不可能永久保存數據(LRU機制),支持分布式,後者除了緩存的同時也支持把數據持久化到磁碟等,redis要自己去實現分布式緩存(貌似最新版本的已集成),自己去實現一致性hash。因為不知道應用場景,不好說一定要用memcache還是redis,說不定用mongodb會更好,比如在存儲日誌方面。
3、緩存量大但又不常變化的數據,比如評論。
4、思路是對的,清晰明了,讀DB前,先讀緩存,如果有直接返回,如果沒有再讀DB,然後寫入緩存層並返回。
5、考慮是否需要主從,讀寫分離,考慮是否分布式部署,考慮是否後續水平伸縮。
6、想要一勞永逸,後續維護和擴展方便,那就將現有的代碼架構優化,按你說的替換資料庫組件需要改動大量代碼,說明當前架構存在問題。可以利用現有的一些框架,比如SpringMVC,將應用層和業務層和資料庫層解耦。再上緩存之前把這些做好。
7、把讀取緩存等操作做成服務組件,對業務層提供服務,業務層對應用層提供服務。
8、保留原始資料庫組件,優化成服務組件,方便後續業務層靈活調用緩存或者是資料庫。
9、不建議一次性全量上緩存,最開始不動核心業務,可以將邊緣業務先換成緩存組件,一步步換至核心業務。
10、刷新內存,以memcached為例,新增,修改和刪除操作,一般採用lazy load的策略,即新增時只寫入資料庫,並不會馬上更新Memcached,而是等到再次讀取時才會載入到Memcached中,修改和刪除操作也是更新 資料庫,然後將Memcached中的數據標記為失效,等待下次讀取時再載入。
大方向兩種方案:
1、腳本同步:自己寫腳本將資料庫數據寫入到redis/memcached。這就涉及到實時數據變更的問題(mysql row binlog的實時分析),binlog增量訂閱Alibaba 的canal ,以及緩存層數據 丟失/失效 後的數據同步恢復問題。
2、業務層實現:先讀取nosql緩存層,沒有數據再讀取mysql層,並寫入數據到nosql。nosql層做好多節點分布式(一致性hash),以及節點失效後替代方案(多層hash尋找相鄰替代節點),和數據震盪恢復了。

『捌』 imgcache是什麼意思

系統輔助

1.img格式是鏡像的一種。可以通過製作數據光碟或者使用虛擬光碟機安裝IMG數據文件。

2.img格式是制定css樣式表的一種樣式,對HTM中的圖片屬性進行修飾。

3.img格式是圖片格式的一種,某些舊系統、游戲中照片是用IMG格式存儲的,而且是多張照片在一起,Ventura Publisher是專門處理img圖像文件的,常見的圖片處理軟體Acdsee和Photoshop也能查看大部分該格式的圖片。

cache n. 高速緩沖存儲器 一種特殊的存儲器子系統,其中復制了頻繁使用的數據以利於快速訪問。存儲器的高速緩沖存儲器存儲了頻繁訪問的 RAM 位置的內容及這些數據項的存儲地址。當處理器引用存儲器中的某地址時,高速緩沖存儲器便檢查是否存有該地址。如果存有該地址,則將數據返回處理器;如果沒有保存該地址,則進行常規的存儲器訪問。因為高速緩沖存儲器總是比主RAM 存儲器速度快,所以當 RAM 的訪問速度低於微處理器的速度時,常使用高速緩沖存儲器。另見 wait state。

Cache的出現是基於兩種因素:首先,是由於CPU的速度和性能提高很快而主存速度較低且價格高,第二就是程序執行的局部性特點。因此,才將速度比較快而容量有限的SRAM構成Cache,目的在於盡可能發揮CPU的高速度。很顯然,要盡可能發揮CPU的高速度就必須用硬體實現其全部功能。

Cache與主存之間可採取多種地址映射方式,直接映射方式是其中的一種。在這種映射方式下,主存中的每一頁只能復制到某一固定的Cache頁中。由於Cache塊(頁)的大小為16B,而Cache容量為16KB。因此,此Cache可分為1024頁。可以看到,Cache的頁內地址只需4位即可表示;而Cache的頁號需用10位二進制數來表示;在映射時,是將主存地址直接復制,現主存地址為1234E8F8(十六進制),則最低4位為Cache的頁內地址,即1000,中間10位為Cache的頁號,即1010001111。Cache的容量為16KB決定用這14位編碼即可表示。題中所需求的Cache的地址為10100011111000。

Cache中的內容隨命中率的降低需要經常替換新的內容。替換演算法有多種,例如,先入後出(FILO)演算法、隨機替換(RAND)演算法、先入先出(FIFO)演算法、近期最少使用(LRU)演算法等。這些替換演算法各有優缺點,就以命中率而言,近期最少使用(LRU)演算法的命中率最高。

瀏覽器緩存

緩存用於存儲一些臨時的文件。在瀏覽網頁的過程中,網頁會自動存儲在用戶的硬碟上。下次再瀏覽相同的網站的時候,系統會自動從硬碟中調出該網頁,既節省了時間也減少了網路的交換。用戶可以自行設定緩存方便其上網的需要。電腦中還存在高速緩沖存儲器和硬碟緩存。緩存的種類:本地伺服器緩存、網頁緩存、硬碟緩存、一級高速緩存、二級高速緩存。

簡單理解

cache是一個高速小容量的臨時存儲器,可以用高速的靜態存儲器晶元實現,或者集成到CPU晶元內部,存儲CPU最經常訪問的指令或者操作數據。

『玖』 redis是個單線程的程序,為什麼會這么快呢

純內存資料庫,如果只是簡單的 key-value,內存不是瓶頸。一般情況下,hash 查找可以達到每秒數百萬次的數量級。

瓶頸在於網路 IO 上。

根據你測的的 10000/s 來看,客戶端和 redis 應該是部署在兩台不同的機器,並且是使用同步的方式請求 redis. 每次請求需要通過網路把請求發送到 redis 所在的機器,然後等待 redis 返回數據。時間大部分消耗在網路傳輸中。

如果把 redis 和客戶端放在同一台機器,網路延遲會更小,一般情況下可以打到 60000 次每秒甚至更高,取決於機器性能。

鎖不是影響性能的主要因素。線程鎖 (mutex_lock) 只有在遇到沖突的情況下性能會下降,而正常情況下,遇到沖突的概率很低。如果只是簡單的加鎖、釋放鎖速度是非常快的,每秒鍾上千萬次沒問題。memcache 內部用到了大量的鎖,並沒有見到性能降低。

線程也不是影響吞吐量的重要因素。如第一點來說,一般情況下,程序處理內存數據的速度遠高於網卡接收的速度。使用線程好處是可以同時處理多條連接,在極端情況下,可能會提高響應速度。

使用 epoll 或 libevent 等因為非同步非阻塞 IO 編程只能這么做。與之對應的是同步阻塞 IO 編程,使用多進程或多線程實現多條連接的處理,比如 apache。一般情況下,非同步非阻塞 IO 模型性能是遠高於同步阻塞 IO 模型的,可以參考 nginx 與 apache 性能的對比。

libevent 並不比 redis 自己實現的 ae_event 慢,代碼多是應為 ae_event 只實現了 redis 需要的功能,而 libevent 則具有更多的功能,比如更快的定時器、buffer event 模型,甚至自帶了 DNS、HTTP 協議的處理。並且 libevent 更通用,而 redis 只專注於 linux 平台。

最後回答問題,快在哪? 1、純內存操作 2、非同步非阻塞 IO

熱點內容
scratch少兒編程課程 發布:2025-04-16 17:11:44 瀏覽:629
榮耀x10從哪裡設置密碼 發布:2025-04-16 17:11:43 瀏覽:357
java從入門到精通視頻 發布:2025-04-16 17:11:43 瀏覽:76
php微信介面教程 發布:2025-04-16 17:07:30 瀏覽:300
android實現陰影 發布:2025-04-16 16:50:08 瀏覽:788
粉筆直播課緩存 發布:2025-04-16 16:31:21 瀏覽:338
機頂盒都有什麼配置 發布:2025-04-16 16:24:37 瀏覽:204
編寫手游反編譯都需要學習什麼 發布:2025-04-16 16:19:36 瀏覽:801
proteus編譯文件位置 發布:2025-04-16 16:18:44 瀏覽:357
土壓縮的本質 發布:2025-04-16 16:13:21 瀏覽:583