天天看點

CYQ.Data V5 分布式緩存MemCached應用開發介紹前言架構內建MemCache架構的代碼重構思維架構裡使用MemCache功能的示範總結

今天大夥還在熱議關于.net core的東西,我隻想說一句:在.net 跨平台叫了這麼多年間,其實人們期待的是一個知名的跨平台案例,而不是一堆能跨平台的消息。

好,回頭說說架構: 

在架構完成資料庫讀寫分離的功能後,開始回想起2年前所構思的:關于架構內建分布式緩存memcached的實作。

之前一直沒動手,是因為思路比較飄,秉承着架構應該簡單幹淨輕量引用無依賴和使用不複雜的思維:

看着memcached的服務端協定,整天思考着自己用socket寫一個用戶端。

後來可能是沒激情,遲遲沒動手。

又在某個時刻,想過偷懶,想動态反射memcached.clientlibrary庫,但一看到它竟然關聯了四個dll,我那純潔的心就有點抗拒它了。

是以日子就這樣飄來複去,這個功能被想起又遺忘......

這幾天,翻看了往昔下載下傳的的相關源碼中,有個叫beitmemcached,掃了一下源碼,發現簡單輕量沒外部引用。

于是就開始改造,并測試了一下,沒發現問題,于是開始思考內建的方式。

架構的緩存類本來很孤單,隻有一個:cachemanage.cs

現在改造完,多了10個類,編繹後dll大小多了30k,說多了也是淚~:

CYQ.Data V5 分布式緩存MemCached應用開發介紹前言架構內建MemCache架構的代碼重構思維架構裡使用MemCache功能的示範總結

1:原有的cachemanage類變更為localcache。

2:cachemanage類變更為抽象類

3:新增memcache,并和localcache一并實作cachemanage抽象類方法。

以上三步,就是核心的思維。

1:從原有的cachemanage裡提取接口icache

2:cachemanage改名webcache并繼承自icache(由于提口提取自本類,是以代碼不需要怎麼調整)

3:建立memcache繼承并實作icache接口。

4:建立cachemanage類,并從webcache處把instance執行個體屬性移到此類中,并傳回對應的icache接口。

因為原來的代碼有一小部分是這樣寫的:cachemanage cache=cachemanage.instance;

因為傳回的類型不一樣,原有代碼受到影響,必須改成:icache cache=cachemanage.instance。

為了避開影響不用改動代碼,是以最終改用定案裡抽象類和抽象方法實作。

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

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

<code>/// &lt;summary&gt;</code>

<code>    </code><code>/// 全局緩存類</code>

<code>    </code><code>/// &lt;/summary&gt;</code>

<code>    </code><code>/// &lt;example&gt;&lt;code&gt;</code>

<code>    </code><code>/// 使用示例:</code>

<code>    </code><code>/// 執行個體化: cachemanage cache=cachemanage.instance;</code>

<code>    </code><code>/// 添加:   cache.add("路過秋天",new mdatatable);</code>

<code>    </code><code>/// 判斷:   if(cache.contains("路過秋天"))</code>

<code>    </code><code>///          {</code>

<code>    </code><code>/// 擷取:       mdatatable table=cache.get("路過秋天") as mdatatable;</code>

<code>    </code><code>///          }</code>

<code>    </code><code>/// &lt;/code&gt;&lt;/example&gt;</code>

<code>    </code><code>public</code> <code>abstract</code> <code>class</code> <code>cachemanage</code>

<code>    </code><code>{</code>

<code>        </code><code>#region 對外執行個體</code>

<code>        </code><code>/// &lt;summary&gt;</code>

<code>        </code><code>/// 傳回唯一執行個體(根據是否配置appconfig.cache.memcacheservers的伺服器決定啟用本地緩存或分布式緩存)</code>

<code>        </code><code>/// &lt;/summary&gt;</code>

<code>        </code><code>public</code> <code>static</code> <code>cachemanage instance</code>

<code>        </code><code>{</code>

<code>            </code><code>get</code>

<code>            </code><code>{</code>

<code>                </code><code>if</code> <code>(</code><code>string</code><code>.isnullorempty(appconfig.cache.memcacheservers))</code>

<code>                </code><code>{</code>

<code>                    </code><code>return</code> <code>localshell.instance;</code>

<code>                </code><code>}</code>

<code>                </code><code>else</code>

<code>                    </code><code>return</code> <code>memshell.instance;</code>

<code>            </code><code>}</code>

<code>        </code><code>}</code>

<code>        </code><code>/// 單機本地緩存</code>

<code>        </code><code>public</code> <code>static</code> <code>cachemanage localinstance</code>

<code>                </code><code>return</code> <code>localshell.instance;</code>

<code>        </code><code>class</code> <code>localshell</code>

<code>            </code><code>internal</code> <code>static</code> <code>readonly</code> <code>localcache instance = </code><code>new</code> <code>localcache();</code>

<code>        </code><code>class</code> <code>memshell</code>

<code>            </code><code>internal</code> <code>static</code> <code>readonly</code> <code>memcache instance = </code><code>new</code> <code>memcache();</code>

<code>        </code><code>#endregion</code>

<code>        </code><code>/// 添加一個cache對象</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>add(</code><code>string</code> <code>key, </code><code>object</code> <code>value);</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>add(</code><code>string</code> <code>key, </code><code>object</code> <code>value, </code><code>double</code> <code>cacheminutes);</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>add(</code><code>string</code> <code>key, </code><code>object</code> <code>value, </code><code>string</code> <code>filename);</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>add(</code><code>string</code> <code>key, </code><code>object</code> <code>value, </code><code>string</code> <code>filename, </code><code>double</code> <code>cacheminutes);</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>add(</code><code>string</code> <code>key, </code><code>object</code> <code>value, </code><code>string</code> <code>filename, </code><code>double</code> <code>cacheminutes, cacheitempriority level);</code>

<code>        </code><code>public</code> <code>abstract</code> <code>dictionary&lt;</code><code>string</code><code>, cachedependencyinfo&gt; cacheinfo { </code><code>get</code><code>; }</code>

<code>        </code><code>public</code> <code>abstract</code> <code>mdatatable cachetable { </code><code>get</code><code>; }</code>

<code>        </code><code>/// 清除所有緩存</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>clear();</code>

<code>        </code><code>public</code> <code>abstract</code> <code>bool</code> <code>contains(</code><code>string</code> <code>key);</code>

<code>        </code><code>/// 獲和緩存總數</code>

<code>        </code><code>public</code> <code>abstract</code> <code>int</code> <code>count { </code><code>get</code><code>; }</code>

<code>        </code><code>/// 獲得一個cache對象</code>

<code>        </code><code>public</code> <code>abstract</code> <code>object</code> <code>get(</code><code>string</code> <code>key);</code>

<code>        </code><code>public</code> <code>t get&lt;t&gt;(</code><code>string</code> <code>key)</code>

<code>            </code><code>object</code> <code>o = get(key);</code>

<code>            </code><code>if</code> <code>(o != </code><code>null</code><code>)</code>

<code>                </code><code>type t = </code><code>typeof</code><code>(t);</code>

<code>                </code><code>try</code>

<code>                    </code><code>return</code> <code>(t)statictool.changetype(o, t);</code>

<code>                </code><code>catch</code> <code>(exception err)</code>

<code>                    </code><code>log.writelogtotxt(err);</code>

<code>                    </code><code>return</code> <code>default</code><code>(t);</code>

<code>            </code><code>return</code> <code>default</code><code>(t);</code>

<code>        </code><code>/// 擷取目标的檔案依賴是否發生更改</code>

<code>        </code><code>/// &lt;param name="key"&gt;&lt;/param&gt;</code>

<code>        </code><code>/// &lt;returns&gt;&lt;/returns&gt;</code>

<code>        </code><code>public</code> <code>abstract</code> <code>bool</code> <code>getfiledependencyhaschanged(</code><code>string</code> <code>key);</code>

<code>        </code><code>/// 擷取緩存對象是否被手工辨別為已更改</code>

<code>        </code><code>public</code> <code>abstract</code> <code>bool</code> <code>gethaschanged(</code><code>string</code> <code>key);</code>

<code>        </code><code>/// 還可用的緩存位元組數</code>

<code>        </code><code>public</code> <code>abstract</code> <code>long</code> <code>remainmemorybytes { </code><code>get</code><code>; }</code>

<code>        </code><code>/// 還可用的緩存百分比</code>

<code>        </code><code>public</code> <code>abstract</code> <code>long</code> <code>remainmemorypercentage { </code><code>get</code><code>; }</code>

<code>        </code><code>/// 删除一個cache對象</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>remove(</code><code>string</code> <code>key);</code>

<code>        </code><code>/// 緩存設定:有則更新,無則添加</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>set(</code><code>string</code> <code>key, </code><code>object</code> <code>value);</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>set(</code><code>string</code> <code>key, </code><code>object</code> <code>value, </code><code>double</code> <code>cacheminutes);</code>

<code>        </code><code>/// 手動對緩存象辨別為已更改</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>setchange(</code><code>string</code> <code>key, </code><code>bool</code> <code>ischange);</code>

<code>        </code><code>/// 更新緩存,緩存存在則更更新,不存在則跳過</code>

<code>        </code><code>public</code> <code>abstract</code> <code>void</code> <code>update(</code><code>string</code> <code>key, </code><code>object</code> <code>value);</code>

<code>        </code><code>public</code> <code>abstract</code> <code>string</code> <code>workinfo { </code><code>get</code><code>; }</code>

<code>    </code><code>}</code>

這裡新增對外一個屬性:localinstance,是因為一但配置了appconfig.cache.memcacheservers後:

原有的本機緩存就自動切換到分布式緩存,為了使用本機緩存依舊可以使用,是以提供localinstance屬性。

一開始是對外三個:instance(自動切換型)、localinstance、meminstance。

大夥可以思考一下,為什麼meminstance被去掉了?感覺有點說不清道不明的感覺。

由于localcache是變更名稱自cachemanage,而cachemanage在以前文章貼過源碼,是以不重複了。

CYQ.Data V5 分布式緩存MemCached應用開發介紹前言架構內建MemCache架構的代碼重構思維架構裡使用MemCache功能的示範總結
CYQ.Data V5 分布式緩存MemCached應用開發介紹前言架構內建MemCache架構的代碼重構思維架構裡使用MemCache功能的示範總結

講完實作的過程和貼完源碼,下面講一下使用過程了:

服務端的檔案是這樣的:

CYQ.Data V5 分布式緩存MemCached應用開發介紹前言架構內建MemCache架構的代碼重構思維架構裡使用MemCache功能的示範總結

運作後的服務是這樣的,這裡開了兩個服務程序,分别對應:11211和11212端口:

CYQ.Data V5 分布式緩存MemCached應用開發介紹前言架構內建MemCache架構的代碼重構思維架構裡使用MemCache功能的示範總結
CYQ.Data V5 分布式緩存MemCached應用開發介紹前言架構內建MemCache架構的代碼重構思維架構裡使用MemCache功能的示範總結

原有的使用方式不變,隻是增加了一行配置,就自動切換到分布式了,是不是從單機過渡到分布式太簡單了。

通常我們不在代碼裡配置,而是配置在:

CYQ.Data V5 分布式緩存MemCached應用開發介紹前言架構內建MemCache架構的代碼重構思維架構裡使用MemCache功能的示範總結

運作的結果是這樣的:

CYQ.Data V5 分布式緩存MemCached應用開發介紹前言架構內建MemCache架構的代碼重構思維架構裡使用MemCache功能的示範總結

使用此架構,不管是進化到資料庫讀寫分離,還是演進到分布式緩存,整個架構的更新過程,隻需增加1行配置檔案。

幾年前就一直在構思,浮浮沉沉地随着架構的演進,如今順水推舟地實作了,想想都覺得有點不可思議。

另外最後top150大神群裡,有人問我,最近寫的文章有人打賞麼?我隻弱弱的回了一句:還沒。

本文原創發表于部落格園,作者為路過秋天,原文連結:http://www.cnblogs.com/cyq1162/p/5617761.html

繼續閱讀