日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

flag -- 诡异的memcache标记

發布時間:2024/4/13 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 flag -- 诡异的memcache标记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

引子   

 ? ??打從去年一路北漂,進入無人貨架行業,業務需求漫天飄,最近總算把工作都規劃齊整。回望過去一年多的時間里,諸多東西值得整理,memcache就是其中一個。

  ?看到java的工資高些,隊伍中好些人都想學習java,美其名曰:技術多元化。奈何團隊中并沒有相關經驗的人,也深知大家殷切的期盼,所以,只能先擼起袖子自己干,看看書、看看博客、看看視頻,兩個小項目就上線了,除memcache以外,過程還算順利,于是就有了這篇文章。

? ? ? ?正值高考,突然感懷,當年的失利,讓自己更加堅強。

? ? ? ? ?                        

?

  

?

背景

  因為目前大部分項目都是.net core ,使用了memcache做為緩存服務器,首先就是 spring boot?里集成?memcache(使用 spymemcached?客戶端),集成過程就不說了,添加依賴,編寫幫助類,通過?@Configuration?注入就可以了。

? ? ? 如果以為這樣就完了,那就沒有這個文章了,真正的故事才剛剛開始.....

問題

  ?配置完成后,就開始讀取已經有緩存,然后就提示:Failed to decompress data,如下圖,返回的內容就是null,但是在命令行能讀出來。另外,我們緩存的都是string,不會存在序列化的問題(一開始還真懷疑過java與.net? string 序列化,好傻好天真)

? ? ? ??

? ? ? ? 因為一開始看上圖是 warn,就沒在意,于是開始了排除方法:

   ?1、java緩存,java?讀取正常。

  ? 2、java緩存,.net 讀取正常。

? ? ? ? 3、直接控制添加, java?讀取正常。

  ? 4、更換java?客戶端為xmemcached

  ? 5、還嘗試了很多.....甚至自己又部署幾個memcache?環境

? ? ? ? 最后,得到一個結論:.net?緩存(使用的是 Enyim.Caching?客戶端),java?無法正常獲取。

  ? 一個詭異的結論,咨詢別人時,都說:memcache?與語言無關!

  ?

失落的解決方案

   嘗試了很多次失敗后,決定讓他涼一涼。終究還是過不了內心的坎,感覺心中有一個東西,不得踏實,又不停的搜索,甚至還在阿里云里發了工單,一開始也懷疑是阿里云的服務器有問題(直接用的阿里的memcache),后來他們技術給我說了一堆

聽不太明白的內容,大概是要用?string?開頭的接口去讀取。這時已經明白,不是讀取不到,而是解碼出錯,返回null而已。

  再后來,就是一個叫flag?的參數引起了我的注意,?大意是說,不同客戶端在緩存時,用了不同的flag?來標記,說什么 java?的是flag 32,.net?的是2之類的,只要修改.net?為32就可以了。?反正聽起來就不靠譜,又到茫茫網絡中去搜索.....

  又過了兩天,感覺不能這么耗下去了,沒有其他方案,想著,還是修改下?Enyim.Caching?源碼試試看。接著 git?clone?源碼,很快定位到 flag?的地方?在?DefaultTranscoder.cs? 74行左右,生成flag的代碼如下

public static uint TypeCodeToFlag(TypeCode code){return 32;//return (uint)((int)code | 0x0100); //修改前}

?

  ? ?其中,TypeCode 是系統中數據類型對應一個 enum,源碼如下,其中?String的值為 18,

namespace System {//// Summary:// Specifies the type of an object.[ComVisible(true)]public enum TypeCode{//// Summary:// A null reference.Empty = 0,//// Summary:// A general type representing any reference or value type not explicitly represented// by another TypeCode.Object = 1,//// Summary:// A database null (column) value.DBNull = 2,//// Summary:// A simple type representing Boolean values of true or false.Boolean = 3,//// Summary:// An integral type representing unsigned 16-bit integers with values between 0// and 65535. The set of possible values for the System.TypeCode.Char type corresponds// to the Unicode character set.Char = 4,//// Summary:// An integral type representing signed 8-bit integers with values between -128// and 127.SByte = 5,//// Summary:// An integral type representing unsigned 8-bit integers with values between 0 and// 255.Byte = 6,//// Summary:// An integral type representing signed 16-bit integers with values between -32768// and 32767.Int16 = 7,//// Summary:// An integral type representing unsigned 16-bit integers with values between 0// and 65535.UInt16 = 8,//// Summary:// An integral type representing signed 32-bit integers with values between -2147483648// and 2147483647.Int32 = 9,//// Summary:// An integral type representing unsigned 32-bit integers with values between 0// and 4294967295.UInt32 = 10,//// Summary:// An integral type representing signed 64-bit integers with values between -9223372036854775808// and 9223372036854775807.Int64 = 11,//// Summary:// An integral type representing unsigned 64-bit integers with values between 0// and 18446744073709551615.UInt64 = 12,//// Summary:// A floating point type representing values ranging from approximately 1.5 x 10// -45 to 3.4 x 10 38 with a precision of 7 digits.Single = 13,//// Summary:// A floating point type representing values ranging from approximately 5.0 x 10// -324 to 1.7 x 10 308 with a precision of 15-16 digits.Double = 14,//// Summary:// A simple type representing values ranging from 1.0 x 10 -28 to approximately// 7.9 x 10 28 with 28-29 significant digits.Decimal = 15,//// Summary:// A type representing a date and time value.DateTime = 16,//// Summary:// A sealed class type representing Unicode character strings.String = 18} } View Code

?

? ? ? ? ?

  根據之前得到的結果,要把 .net?客戶端的flag?設置成32,于是,直接返回32,代碼生成上傳,不試不知道,一試嚇一跳,竟然正常了。java?能正常返回緩存內容了,如下圖,正常打印了

  

? ? ? ?剛開始真是高興了足足10秒中,畢竟嘗試了很多次失敗,但轉念一想,現在所有的項目,都得去引用自己編譯的這個版本,以后如果?Enyim.Caching?升級了,我還得去重新下載、編譯,所有項目又要重新引用,想想就后怕!

? ? ? ?于是,第一次有了這樣的感覺:問題解決了,但是很多失落!弄完回到家,看我一臉無趣,媳婦還安慰說:“今天沒解決,明天再來,明天不行,后天再來,總會撥云見日的!”

?

升級版解決方案

  缺陷的解決方案,一直縈繞心頭,揮之不去,于是,還是忍不住去查詢新的方案,還特意發起了一個博問,不過就 dudu?回復了,雖然沒有直接解決,也給了一些新的提示,并順利的看到了?spymemcached?的源碼。找到了

  解碼的類?SerializingTranscoder.java ,對于?String?并未做處理,也沒有解碼的問題。?解碼部分源碼如下,可以看到,對于?String是直接調用??decodeString

public Object decode(CachedData d) {byte[] data = d.getData();Object rv = null;if ((d.getFlags() & COMPRESSED) != 0) {data = decompress(d.getData());}int flags = d.getFlags() & SPECIAL_MASK;if ((d.getFlags() & SERIALIZED) != 0 && data != null) {rv = deserialize(data);} else if (flags != 0 && data != null) {switch (flags) {case SPECIAL_BOOLEAN:rv = Boolean.valueOf(tu.decodeBoolean(data));break;case SPECIAL_INT:rv = Integer.valueOf(tu.decodeInt(data));break;case SPECIAL_LONG:rv = Long.valueOf(tu.decodeLong(data));break;case SPECIAL_DATE:rv = new Date(tu.decodeLong(data));break;case SPECIAL_BYTE:rv = Byte.valueOf(tu.decodeByte(data));break;case SPECIAL_FLOAT:rv = new Float(Float.intBitsToFloat(tu.decodeInt(data)));break;case SPECIAL_DOUBLE:rv = new Double(Double.longBitsToDouble(tu.decodeLong(data)));break;case SPECIAL_BYTEARRAY:rv = data;break;default:getLogger().warn("Undecodeable with flags %x", flags);}} else {rv = decodeString(data);}return rv;} View Code

?

?

? ? ?decodeString?代碼如下,可見并無特殊處理

/*** Decode the string with the current character set.*/protected String decodeString(byte[] data) {String rv = null;try {if (data != null) {rv = new String(data, charset);}} catch (UnsupportedEncodingException e) {throw new RuntimeException(e);}return rv;}

?

? ? ?

? ? ? 再細看?SerializingTranscoder.java?的處理邏輯,在解碼之前,有壓縮標志,以及?decompress()?方法,?這個方法在?BaseSerializingTranscoder.java?中,源代碼如下,正好有,有一個?catch?會輸出,最早看到的錯誤信息:Failed to decompress data

getLogger().warn("Failed to decompress data", e); 找到了問題的發生地兒,離解決方案就不遠了。 第一現場很重要。

/*** Get the object represented by the given serialized bytes.*/protected Object deserialize(byte[] in) {Object rv=null;ByteArrayInputStream bis = null;ObjectInputStream is = null;try {if(in != null) {bis=new ByteArrayInputStream(in);is=new ObjectInputStream(bis);rv=is.readObject();is.close();bis.close();}} catch (IOException e) {getLogger().warn("Caught IOException decoding %d bytes of data",in == null ? 0 : in.length, e);} catch (ClassNotFoundException e) {getLogger().warn("Caught CNFE decoding %d bytes of data",in == null ? 0 : in.length, e);} finally {CloseUtil.close(is);CloseUtil.close(bis);}return rv;} View Code

?

? ? ?

? ? ? 既然問題出在“解壓”這里,那為什么我把 flag 設置成32就可以了呢,再看源碼,判斷是否解壓的如下:

? ? ??static final int COMPRESSED = 2;

 if ((d.getFlags() & COMPRESSED) != 0) {
  data = decompress(d.getData());
 }

.net 里默認是 18 | 0x0100 = 274 274 & ?2 = 2 不等于0,會去解壓,然后出錯了。

32 & 2 =0, 不解壓,正常。

這里其實驗證了,flag與客戶端無關。壓縮標志與數據類型有關。

 ? 問題已經明確了,只要程序不走解壓就是正常的,并且,這些參數,都是類內部的狀態,外面無法修改,那可以擴展嗎?使用自己的解碼類來實現,肯定是可以的,看?SerializingTranscoder?與?BaseSerializingTranscoder?的繼承關系就知道,

? ? ?再看? get?方法 memcachedClient.get(String key, Transcoder<T> tc),支持自定義??Transcoder,?接下來,問題就簡單了,自定義一個?Transcoder?繼承??BaseSerializingTranscoder?實現?Transcoder,不用解壓,直接解碼。

? ? ?最后,其實,我只是在? SerializingTranscoder? 基礎上,把?static final int COMPRESSED = 0,就可以了,都不解壓。?獲取代碼如下

HMSerializingTranscoder transcoder = new HMSerializingTranscoder(); return memcachedClient.get(key,transcoder);

?

?

結語

  分析到此,問題明了,方案明確,水到渠成,問題解決了。在不修改第三方源碼的基礎上,通過擴展解決了,也不用擔心第三方升級的問題了,這樣就比第一種別扭的方案舒服多了。

  第一次感受到閱讀源碼,與深究一個問題的帶來的收獲 -- 杠杠的

?

  ?成為一名優秀的程序員!

?

版權聲明:
作者:J2


編輯:妞妞
妞妞主頁
出處:http://www.cnblogs.com/jijunjian/
本文版權歸作者和博客園共有,歡迎轉載,大家好,才是真的好!

總結

以上是生活随笔為你收集整理的flag -- 诡异的memcache标记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久精品欧美一区 | 色婷婷综合久久久久中文一区二区 | 欧美午夜精品一区二区三区电影 | 有码一区二区三区 | 狠狠躁夜夜躁av无码中文幕 | 13日本xxxxxⅹxxx20 | 偷拍亚洲综合 | 国产视频你懂得 | avwww| 全部孕妇毛片丰满孕妇孕交 | 91超薄肉色丝袜交足高跟凉鞋 | 久久精品这里有 | 相亲对象是问题学生在线观看 | 91爱爱com | 伊人国产在线视频 | 九九色影院 | 免费黄色av电影 | 天堂av资源在线观看 | 美腿丝袜一区二区三区 | 久草网站 | 91美女在线 | 超碰999| 成人高清免费 | 亚洲色图第一页 | 三级男人添奶爽爽爽视频 | 成人做爰69片免费观看 | 视频在线观看你懂的 | 欧美91精品久久久久国产性生爱 | 中国a级大片 | 免费一级特黄特色毛片久久看 | 春宵av| 一二三四区在线 | 超碰在线影院 | 日韩精品少妇 | 成人午夜免费视频 | 亚洲成年人专区 | 欧美性生交xxxxxdddd | 亚洲在线看 | 人妻与黑人一区二区三区 | 国产精品视频导航 | www欧美在线 | 91视频二区| 国产成人精品久久二区二区 | 女人扒开屁股让男人捅 | 美女露胸无遮挡 | 久久久精品影视 | 国产色悠悠 | av合集| 中文字幕有码在线 | 一本大道综合伊人精品热热 | 91精品久久久久久久久久 | 蜜臀久久99精品久久久画质超高清 | 亚洲激情五月 | caopor超碰 | 日本三级韩国三级美三级91 | 国产黄| 在线观看中文字幕一区二区 | 国产精品第2页 | 噼里啪啦国语版在线观看 | 欧美首页 | 日本a级在线 | 免费观看av的网站 | 亚欧日韩av | 四色成人网 | 国产精品无码乱伦 | xxxx精品| 国产精品白浆一区二小说 | 少妇无套内谢久久久久 | 久久伊人国产 | 99免费精品 | 爱爱免费小视频 | 福利视频在线播放 | 中文字幕1区 | av无码精品一区二区三区 | 欧美一区二区三区久久精品 | 中国特级黄色片 | 污污网址在线观看 | 欧美日韩中文在线视频 | 亚洲精品成人久久 | 国产四区 | 日韩欧美视频免费观看 | 一级黄色片免费在线观看 | 黄色综合网站 | 加勒比久久综合 | 国产视频xxxx | 嫩草视频在线观看免费 | 蜜臀av在线观看 | 日韩一区不卡视频 | 亚洲一区自拍偷拍 | 秋霞av一区二区三区 | 亚洲最新偷拍 | 婷婷丁香花五月天 | 韩国三级hd两男一女 | 国产乱码精品一区二三赶尸艳谈 | 国产激情一区二区三区四区 | 国产精品日韩欧美大师 | 成人午夜av | 伊人资源 | 久久国产视频精品 |