前方:
其實完成這個功能之前,我就在思考:是先把想法寫了來,和大夥讨論讨論後再實作,還是實作後再寫文論述自己的思維。
忽然腦後傳來一個聲音說:你發文後會進入發呆階段。
是以還是靜下心,讓我輕輕地把代碼撸完再說。
最近這幾天,自己在大腦裡演練過各種技術難點,解決方案,推敲了各種該解決的問題,覺的差不多了,才決定撸碼。
忽然發覺,原來代碼是可以寫在大腦裡的。
要是你看到一個員工坐着2天沒寫一行代碼,說明人家是高手,正在大腦程式設計。
好,不扯,回正文!
傳統orm的二級緩存為何失效?
有些orm會提供:如hibernate。
有些不提供:如ef,不提供是因為知道提供了也沒啥鳥用,因為:
1:你不能強迫一個項目全部用單實體程式設計,多表時,使用者更偏向于執行sql語句。
2:沒有分布式緩存做為基礎,解決不了多應用程式部署的緩存政策問題。
是以:
1:若控制不了整個項目使用者的sql語句,單機的搞不了。
2:沒有分布式緩存做基礎,分布式的都搞不了。
這也是為啥ef一直不提供,是因為看到hibernate雖然提供但并沒多大卵用的原因吧!
疑惑資料庫已有緩存,為何架構還要造孽?
主要原因:
1:資料庫從請求到建立緩存,需要時間(架構緩存可以減緩資料庫緩存失效時壓力)
2:資料庫是有連結數限制的,不可能允許大量并發的直連,需要外界分壓。
3:資料庫的緩存是單機性。
4:資料庫發資料往伺服器的時間比本機緩存的長。
自動緩存設計前的一些思考:
1:一開始我思考的緩存政策,是細化到行或列,于是了解資料庫自身緩存後發現資料庫目前也隻是做了以表為機關。
2:mssql是有提供sqldependency的緩存依賴項的,它可以從資料庫層面通知你的資料何時失效。
3:但是sqldependency和sqlcommand依賴太深,無法在所有資料庫層面通用。
4:sqldependency的緩存依賴隻能在本地緩存。
5:其它資料庫不支援依賴通知。
6:是以方案隻能通過全局執行與分析,來處理緩存及失效政策。
7:單機時:全局攔截分析,如何分析出表?
8:應用分布式時:緩存及時失效?
9:使用者直接修改資料庫時:緩存如何失效?
還有好多好多問題,一直在思考......
緩存什麼?
1:緩存單個對象時,是直接存檔對象的,cache傳回時會根據本地或是遠端選擇是否clone傳回。。
2:緩存清單時:隻存檔字段類型僅包含:(數字、布爾、字元、時間、guid)的字段,并轉成json字元串存檔。
技術細節:
a:一個對象存檔在本機時,存檔的是引用(可能出現誤寫操作);存檔在分布式時,存檔的不是引用,這會在使用時出現不确定性。
b:大對象的存檔,在緩存來去間需要序列化和反序列化,性能上降低很多。
是以:将清單轉成json存檔,拿到時再還原,可以同時解決a和b的問題。
簡單的說,如果對象有長字段,或者有二進制資料,是不會被緩存的,是以mssql的timestamp字段就不要用了;
如果要用:appconfig.db.hiddenfields="字段名",把它隐藏了也行。
緩存時間?
考慮到通常通路量低時都是在中午和晚上的時間,是以,将緩存的對象的時間随機分布(早上的分布在中午失效,下午的分布在晚上失效)
考慮到分頁時的查詢,通常都關注前面幾頁,是以前面幾頁的資料,時間如上的時間段分布。
分頁後面的資料,隻預設2分鐘的緩存時間。
其它規則有待讨論......
緩存多大?
1:在單機狀态,檢測到記憶體的可用比例低于15%時,則不再接受緩存。
2:在分布式緩存狀态,暫時有多少扔多少。
緩存如何失效:
1:攔截請求:(包括(maction)增删改查+(mproc)執行自定義語句+(mdatatable)批量方法)
2:分析語句的關聯表(單表的可以拿表名,視圖的拿關聯結構涉及的表名,存儲過程(目前沒法),自定義sql(語句分析出表名),批量(直接拿表名)
3:技術難點:如何從未知的sql或視圖中準确的分析出所有關聯的表。
4:緩存失效:執行以下方法應該失效:增删改,執行exenonquery,批量語句。
5:技術難點:
1:對于視圖(關聯了多個表,如何根據一個表名,關聯到相應涉及的視圖語句失效?)
2:對于分布式的應用,a服務更新,如何b伺服器也失效。
如何處理修改頻繁的表:
1:一開始想增加配置,讓使用者設定不參與緩存的表,認真思考後,發現根據緩存失效的時間和次數,可自動分析判斷一個表是否修改頻繁。
2:表操作相關增删查時,該表被置為失效(相關緩存會被移除),此時設定好時間間隔(6秒),在此時間段對該表相關的不緩存,同時送出的緩存删指令也可以無視。
3:對被分析出為修改頻繁的表該如何處理?延長相應的不緩存時間,或是??還需要思考!!!
緩存失效的粒度能不能小?
1:目前的失效,和資料庫一樣,是以表為機關的。
2:對于插入操作,不會影響某一條資料的讀取(是以單條資料的查詢,是不應該受到插入操作的影響的)
3:還有其它情形是必然不會影響的?
架構有自動緩存,業務需不需要緩存?
1:資料庫有自動緩存,架構的也可以自動緩存。
2:架構有自動緩存,同理業務也可以有緩存。
架構能處理的粒度是有限的,不能細到具體的行或列的緩存級别,是以在業務複雜和并發到一定量後,業務緩存是必要的。
資料庫有緩存,業務也可做緩存,為何還思考往架構增加自動緩存?
1:資料庫的預設緩存是固定的,需要配置,各種資料庫環境不一緻。
2:資料庫連結池預設是固定的。
3:業務加緩存的事,往往是後期的動作。
現另一個現狀是:
1:.net 群體,存在很多國中級的開發人員,這部分人員的技術成長相對較慢,對緩存或性能調優并不熟。
2:國内有很多的中小網站,預設都抗不起并發,攻擊成本很小,幾百上千個并發就可以挂你站了。
是以,既然有現實的問題,就可以有對應的解決方案。
v5架構此功能的出現,就是為了從基礎層面統一解決這些問題。
隻有當.net行業不在有慢網站的存在,整體提升檔次了,有良好的口碑,才會引進更多的boss選用 .net,大夥所期待的.net春天也就近了。
v5的目前解決的問題:
總體而言,要實作這個功能,核心要解決以下問題:
下面我來将技術一點一點出賣:
5:aop攔截問題:
首先,要實作這功能,就得全局攔截,掃蕩過源碼或用過v5的同學,聽說過架構本身就有aop的吧;
其次,得改造這個aop:架構預設有一個空aop,當外部有aop裝載的時候,會替換掉這個空aop。
要實作這個自動緩存:本想在空aop裡實作,放着浪費,但若使用者自定義的aop被裝載,又會被替換掉,走不通...
方案想了三四個,思考了三四夜,最後還是在撸碼時才确定了現在的模式(這個告訴我們,想的差不多了就該撸碼了,要100%想通再撸不太靠譜):
于是,我這樣做了:
原有的aop,改名成interaop,不過是挂名的,因為它沒有繼承iaop接口,而且從原本的單例變更成多例模式。
這裡可以貼兩行代碼,意思是:在bengin和end方法調用了外部aop的接口,并根據外部aop的狀态決定後續的執行流程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public aopresult begin(aopenum action)
代碼最後很少,但沒想出來之前,2天都搞不定。
1:基礎單表、視圖操作
a:單表,這個是最簡單的,傳遞進來的就是表名;
b:視圖,這個麻煩一點,傳遞的是視圖名;
于是,如何從視圖擷取相關參與的表名?你現在應該不知道,我來告訴你吧:
dbdatareader sdr=....
datatable dt = sdr.getschematable();
這條語句,可以通殺所有的資料庫,不用去n種資料庫裡搜各種中繼資料藏在哪了!!!
2:多表sql語句操作:
對于sql語句,可以用上面的方法,執行一個datareader再拿,但我弄了一個簡單的方法來找關聯表:
41
internal static list gettablenamesfromsql(string sql)
有可能會找多,找到後,再過濾一下名稱是不是資料庫裡的表就可以了。
3:直接操作資料庫
一開始設定的思維,是動态建立一個表,字段大概是這樣的:
表名 更新時間
然後如果手工操作資料庫,可以手工更改時間,也可以用觸發器引發這裡的更新。
然後背景線程定時掃這個表,就知道有沒有表被更新了。
不過--------v5目前并木有實作它,隻是開放了一個接口,可以讓你在代碼裡調用移除緩存。
這個方法就是:
public abstract partial class cachemanage
{
}
4:跨伺服器操作
這個本來是簡單的,後來又想麻煩了,因為要兼顧性能問題,緩存移除可能會頻繁的問題。
後來,通過增加了緩存類型,來識别本地緩存或分布式緩存,來差別寫代碼:
private static void setbasekey(string basekey, string key)
6:緩存失效問題
這個問題,流程本來很簡單的:
但思考到cache多,而且分布式時,傳回會卡,是以删除cache操作就變成線程處理了。
後來為了避免線程多開,又把類改成了單例(一開始是多執行個體的)
現在,又把這線程的線程開啟,放到localcache裡和另一個線程作伴了,然後這個單例類又變更成了靜态類。
v5架構怎麼使用這功能:
更新版本到最新版即可!
總結:
1:沒有這個功能之前:架構解決了三大問題:程式設計架構的統一(自動化)、資料庫壓力(讀寫分離)、伺服器壓力(分布式緩存)。
2:此功能的存在:是針對從基礎層面提升行業項目的整體水準。
3:最近大腦有點發春,一個個創新idea不斷的從我大腦冒出來,折騰的我好累:
要思考架構、落實架構代碼、要寫文分享,寫架構demo、群裡解答。
4:開源不賺錢,又投入這麼多精力,隻能把它當理想了,希望它有天成為.net項目的标配資料層。
5:我部落格是有打贊插件的,哈。