国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - ASP.NET教程 - 發布一個基于TokyoTyrant的C#客戶端開源項目

發布一個基于TokyoTyrant的C#客戶端開源項目

2019-09-07 15:39腳本之家 ASP.NET教程

目前在網上關于TokyoCabinet(以下簡稱TC)和TokyoTyrant(以下簡稱TT)的資料已相對豐富了,但在.NET平臺上的客戶端軟件卻相對匱乏,因為做Discuz!NT企業版的關系,兩個月前開始接觸TC和TT,開始寫相關的客戶端代碼。

這里開放的是客戶端主要功能代碼,開源的目的一方面是希望更多的人來學習研究TC和TT,同時大家可以下載本C#源碼繼續優化提升性能,同時查找BUG,必定本人精力能力有限,而Discuz!NT企業版的功能點又太多(抽空會多寫文章進行介紹)實在有些力不從心了,呵呵:)

       好了,為了便于使用,下面先對源碼中的項目文件進行說明:

      源碼包中包括三個項目:
      1.Discuz.EntLib.TokyoTyrant 核心功能代碼(目前名空間暫以產品命名)
      2.TTSample 主要用于加載測試數據,并對比SQLSERVER數據庫的創建查詢功能的速度。
      3.TTSampleConsole 使用核心功能代碼的例子(本文中會介紹其中主要功能)

       其中Discuz.EntLib.TokyoTyrant中類圖如下:
發布一個基于TokyoTyrant的C#客戶端開源項目
該客戶端有如下特點: 
支持TcpClient連接池 
支持UTF-8編碼 
支持初始化鏈接數,鏈接過期時間,最大空閑時間,最長工作時間等設置 

下面介紹一下如何使用: 
1.初始化鏈接池: 

復制代碼代碼如下:

pool = TcpClientIOPool.GetInstance("dnt_online");//鏈接池名稱(即DNT在線表) 
pool.SetServers(new string[] { "10.0.4.66:11211"}); 
pool.InitConnections = 8; 
pool.MinConnections = 8; 
pool.MaxConnections = 8; 
pool.MaxIdle = 30000; 
pool.MaxBusy = 50000; 
pool.MaintenanceSleep = 300000; 
pool.TcpClientTimeout = 3000; 
pool.TcpClientConnectTimeout = 30000; 
pool.Initialize(); 



2.CRUD操作: 
創建一條記錄(以DISCUZ!NT在線表字段為例): 

復制代碼代碼如下:

IDictionary<string, string> columns = new System.Collections.Generic.Dictionary<string, string>(); 
columns.Add("olid", i.ToString()); 
columns.Add("userid", i.ToString()); 
columns.Add("ip", "10.0.7." + i); 
columns.Add("username", "用戶" + i); 
columns.Add("nickname", "用戶" + i); 
columns.Add("password", ""); 
columns.Add("groupid", "5"); 
columns.Add("olimg", ""); 
columns.Add("adminid", "0"); 
columns.Add("invisible", "0"); 
columns.Add("action", "0"); 
columns.Add("lastactivity", "1"); 
columns.Add("lastposttime", DateTime.Now.ToString()); 
columns.Add("lastpostpmtime", DateTime.Now.ToString()); 
columns.Add("lastsearchtime", DateTime.Now.ToString()); 
columns.Add("lastupdatetime", DateTime.Now.ToString()); 
columns.Add("forumid", "0"); 
columns.Add("forumname", ""); 
columns.Add("titleid", "0"); 
columns.Add("title", ""); 
columns.Add("verifycode", ""); 
columns.Add("newpms", "0"); 
columns.Add("newnotices", "0"); 
TokyoTyrantService.PutColumns(TTPool.GetInstance(), i.ToString(), columns, true);//true表示如tc中有記錄則覆蓋,沒有則創建該記錄 




查詢操作: 
首先構程過一個查詢(條件)對象,比如查詢字段olid = 1的在線用戶信息,則該對象定義如下: 
new Query().NumberEquals("olid", 1) 

然后將其放入TokyoTyrantService的QueryRecords方法中(注意綁定鏈接池),如下: 

var qrecords = TokyoTyrantService.QueryRecords(TTPool.GetInstance(), new Query().NumberEquals("olid", 1)); 
//遍歷當前結果集 
foreach (var k in qrecords.Keys) 

var column = qrecords[k]; 
...數據綁定操作 


更復雜的查詢,如下(查詢forumid = 16 and userid<1000 ,同時按userid字段倒序排列的前三條記錄): 

qrecords = TokyoTyrantService.QueryRecords(pool, new Query().NumberGreaterThanOrEqual("forumid", 16). 
NumberLessThan("userid", 1000).OrderBy("userid", QueryOrder.NUMDESC).LimitTo(3, 0)); 
這里的比較運行符可以參見源碼中的枚舉類型,如下: 

復制代碼代碼如下:

public enum QueryOperation 

STREQ = 0, // # 查詢條件: 表示與操作對象的文字內容完全相同(=) 
STRINC = 1, // # 查詢條件: 表示含有操作對象文字的內容(LIKE ‘%文字%') 
STRBW = 2, // # 查詢條件: 表示以操作對象的文字行列開始(LIKE ‘文字%') 
STREW = 3, // # 查詢條件: 表示到操作對象的文字行列結束(LIKE ‘%文字') 
STRAND = 4, // # 查詢條件: 表示包含操作對象的文字行列中右逗號分開部分的字段的全部(name LIKE ‘%文字㈠%' AND name LIKE ‘%文字㈡%') 
STROR = 5, // # 查詢條件: 表示包含操作對象文字段中逗號分開部分的其中一部分(name LIKE ‘%文字㈠%' OR name LIKE ‘%文字㈡%') 
STROREQ = 6, // # 查詢條件: 表示與操作對象文字段中逗號分開部分的其中某部分完全相同( name = ‘文字㈠' OR name =‘文字㈡') 
STRRX = 7, // # 查詢條件: 表與與常規表達式匹配 
NUMEQ = 8, // # 查詢條件: 表示等于操作對象的數值(=) 
NUMGT = 9, // # 查詢條件: 表示比操作對象的數值要大(>) 
NUMGE = 10, // # 查詢條件: 表大于或等于操作對象的數值(>=) 
NUMLT = 11, // # 查詢條件: 表示比操作對象的數值要小(<) 
NUMLE = 12, // # 查詢條件: 表示小于或等于操作對象的數值(<=) 
NUMBT = 13, // # 查詢條件: 表示其大小處于操作對象文字段中被逗號分開的兩個數值的中間(between 100 and 200) 
NUMOREQ = 14, // # 查詢條件: 表示其大小處于操作對象文字段中被逗號分開的兩個數值的中間(between 100 and 200) 
NEGATE = 1 << 24, // # 查詢條件: 負標志negation flag 
NOIDX = 1 << 25 // # 查詢條件: 非索引標志 


查詢指定主鍵(如本例中的olid,效率最高) 

復制代碼代碼如下:

var qrecords = TokyoTyrantService.GetColumns(pool, new string[]{"1", "2", "3"}); 
foreach (string key in qrecords.Keys) 

var column = qrecords[key]; 


更新操作: 
因為TC的TCT結構沒有提供直接更新記錄中某一字段的功能,所以只能全部取出相關記錄的所有字段,然后再更新全部字段(這種做法的效率不高,但在MONGODB中是可以更新部分字段)。所以要組合使用查詢和創建操作中的語法,即選查出相應記錄,然后再使用PutColumns方法更新該記錄,形式如下: 

復制代碼代碼如下:

var qrecords = TokyoTyrantService.QueryRecords(TTPool.GetInstance(), new Query().NumberEquals("olid", 1)); 
foreach (var k in qrecords.Keys) 

var column = qrecords[k]; 
...數據綁定操作 
TokyoTyrantService.PutColumns(TTPool.GetInstance(), column["olid"], columns, true);//column["olid"]為主鍵,類似數據庫里的主鍵,以其為查詢條件,速度最快 


刪除操作 
該操作有兩種執行方法,一種是選查詢出符合條件的記錄,然后再刪除(依次刪除),一種是直接給定要刪除的主鍵直接刪除(效率比前者高)。第一種(可以針對不用字段進行查詢,并將相應結果的主鍵做了刪除依據) 

復制代碼代碼如下:

var qrecords = TokyoTyrantService.QueryRecords(TTPool.GetInstance(), new Query().NumberEquals("userid", 1)); 
foreach (var k in qrecords.Keys) 

var column = qrecords[k]; 
...數據綁定操作 
TokyoTyrantService.Delete(TTPool.GetInstance(), column["olid"]);//column["olid"]為主鍵,類似數據庫里的主鍵 



第二種(刪除olid為1或2或3或4的鍵值記錄,只能刪除以主鍵為條件的記錄): 
TokyoTyrantService.DeleteMultiple(pool, new string[] { "1", "2", "3", "4" }); 

創建索引 
TC中支持幾種類型的字段索引如下(經常用的是數值型和字符型): 

復制代碼代碼如下:

/// <summary> 
/// 索引類型 
/// </summary> 
public enum IndexOption : int 

LEXICAL = 0, // # 文本型索引 
DECIMAL = 1, // # 數值型索引 
TOKEN = 2, // # 標記倒排索引. 
QGRAM = 3, // #QGram倒排索引. 
OPT = 9998, // # 9998, 對索引優化 
VOID = 9999, // # 9999, 移除索引. 
KEEP = 1 << 24 // # 16777216, 保持已有索引. 



比如在線表中經常用的字段索引設置如下: 

復制代碼代碼如下:

TokyoTyrantService.SetIndex(pool, "olid", IndexOption.DECIMAL); 
TokyoTyrantService.SetIndex(pool, "userid", IndexOption.DECIMAL); 
TokyoTyrantService.SetIndex(pool, "password", IndexOption.LEXICAL); 
TokyoTyrantService.SetIndex(pool, "ip", IndexOption.LEXICAL); 
TokyoTyrantService.SetIndex(pool, "forumid", IndexOption.DECIMAL); 
TokyoTyrantService.SetIndex(pool, "lastupdatetime", IndexOption.DECIMAL); 


3.其它常用操作 

復制代碼代碼如下:

LimitTo(int max, int skip):類似于MYSQL中的LIMIT方法,其中max如同mssql中的TOP,而skip則表示跳過多少條記錄(類似LINQ中的那個Skip方法) 
Vanish(TcpClientIOPool pool);清空所有記錄 
QueryRecordsCount(TcpClientIOPool pool, Query query)//查詢指定條件的記錄數 
GetRecordCount(TcpClientIOPool pool)//返回當前表中的記錄總數 
GetDatabaseSize(TcpClientIOPool pool);//獲取數據庫(表)信息 
IteratorNext(TcpClientIOPool pool)//一個迭代器,用于遍歷所有記錄 



4.因為其兼容Memcached,所以提供方法支持(鍵/值對) 

復制代碼代碼如下:

Put(TcpClientIOPool pool, string key, string value, bool overwrite)//該操作方法將不像Put那樣獲取服務器端返回的信息 
PutFast(TcpClientIOPool pool, string key, string value)//快速存儲鍵值對(不再獲取服務端返回信息). 如鍵值已存在則將被覆蓋 
PutMultiple(TcpClientIOPool pool, IDictionary<string, string> items) //一次添加多值 
Delete(TcpClientIOPool pool, string key)//刪除指定鍵的記錄 
DeleteMultiple(TcpClientIOPool pool, string[] keys)//刪除指定鍵組的記錄 
Get(TcpClientIOPool pool, string key)//獲取指定鍵的記錄(單條) 
GetSize(TcpClientIOPool pool, string key)//獲取指定鍵的大小 
GetColumns(TcpClientIOPool pool, string[] keys)//獲取指定鍵組的記錄(多條) 


5.排序 

public enum QueryOrder 

STRASC = 0, // # 排序類型: 表示按照文本型字段內的文本內容在字典中排列順序的升序 
STRDESC = 1, // # 排序類型: 表示按照文本型字段內的文本內容在字典中排列順序的降序 
NUMASC = 2, // # 排序類型: 表示按照數值大小的升序 
NUMDESC = 3 // # 排序類型: 表示按照數值大小的降序 


用法(如降序并取前16條記錄): 

qrecords = TokyoTyrantService.QueryRecords(pool, new Query().OrderBy("userid", QueryOrder.NUMDESC).LimitTo(16, 0)); 
注意:盡量避免對大數據集(如100w條記錄)進行排序,那樣耗時會很嚴重。所以盡量在OrderBy之前指定查詢條件,從而縮減查詢結果集的尺寸。 

其它說明: 
TT的啟動參數(這里以TCT類型為例): 
注:網上有一些關于TC+TT與MONGODB,Redis的速度測試,所以這里我想有必要對TT的啟動參數做一下介紹,因為這會關系到最終的測試結果。 
因為兩者都使用了MMAP模式,而TC+TT要使用MMAP,就要使用下面參數: 

xmsiz:指定了TCHDB的擴展MMAP內存大小,默認值為 67108864,也就是64M,如果數據庫文件超過64M,則只有前部分會映射在內存中,所以寫入性能會下降。 
bnum: 指定了bucket array的數量。推薦設置bnum為預計存儲總記錄數的0.5~4倍,使key的哈希分布更均勻,減少在 bucket內二分查找的時間復雜度。 

比如有100w條記錄,這里可以使用下面命令行啟動ttserver: 
ttserver -host 10.0.4.66 -port 11211 -thnum 1024 -dmn -pid /ttserver/ttserver.pid -log /ttserver/ttserver.log -le -ulog /ttserver/ -ulim 256m -sid 1 -rts /ttserver/ttserver.rts /ttserver/database.tct#bnum=1000000#rcnum=1000000#xmsiz=1073741824 (注:1073741824=1G) 

當然TTServer中針對不同的數據庫(TC中支持6種),都有相應的參數進行啟動配置(有重復),這會導致的查詢和插入數據的結果上有很大的差異,更多的內容可以參見這個鏈接。 

下面我將自己對TC+TT(僅使用TCT文件類型,其它5種類型都比這個類型快許多)與MONGODB的測試結果做一下說明: 
機器是一個普遍臺式機:1.5g內存+1.5gCPU,64位的centos機器,150g硬盤。 

mongodb (centos 64bit) : 
插入1000000 條記錄,耗時:250377毫秒 
對1000000條記錄,查詢10000 次記錄,耗時:8100毫秒 (偶爾出現7500毫秒) (查詢"_id"主鍵速度在6995毫秒上下) 
對1000000條記錄,查詢100000 次記錄,耗時:77101毫秒 

ttcache(centos 64bit,使用上面的啟動參數): 
創建 1000000 條數據,耗時 589472毫秒 
對1000000條記錄,查詢 10000 次數據,耗時 4843毫秒 
對1000000條記錄,查詢 100000 次數據,耗時 47903毫秒 

注:查詢條件動態變化,以模擬實際生產環境。 
比較發現MONGODB插入速度要比TTCACHE快至少一倍(MONGODB在WINDOWS下也是如此),但10000次查詢速度會慢大約40%-50%。這里的查詢和插入操作都是每做一次操作就Connect一次服務器,操作結束時則將當前鏈接放到鏈接池中,而不是開啟一個長鏈接來做批量操作。其中TTSERVER所使用的客戶端分別是本文的這個工具, MONGODB則使用的是MongoDB.Driver。 
下面是MSSQL數據庫操作結果: 
批量創建 1000000 條數據,耗時 9020196毫秒 
批量查詢 10000 條數據,耗時 106040毫秒 
批量查詢 100000 條數據,耗時 773867毫秒 

我想進行這類測試,還是不要使用什么WINDOWS(盡量MONGODB在WINDOW下插入數據的速度已很快)或其它操作系統。而應該使用LINUX(盡量是64位)。當然內存要盡量的大,因為盡管TC+TT已很省內存(必定符合日本的國情,資源少還要多辦事),但如果要提升查詢和插入速度,還是建議4g以上的內存做測 
試。而MONGODB本來對內存要求很高(包括CPU)。 

因為mongodb的插入速度非常快,且在數據庫大量可以新建文件來存儲新的數據(不像TCT使用一個數據文件),所以在更大級別的數據量插入上依然性能穩定。看來將它視為海量數據存儲的分布解決方案還是很有可行性的。當然我目前正在考慮一個架構,就是將MongoDb和TC/TT組合起來,實現讀寫分離(即將TC作為讀數據庫slavedb,并發性和查詢速度快),而將MongoDb作為寫數據庫masterdb(更新和插入速度快)。將分布式的MongoDb數據文件與前端TC中的文件依次對應(使用C#代碼實現兩者之間的數據同步和邏輯調用),這樣融合兩者各自的優勢的結果。當然目前這只是想法,且離文本的內容越來越遠了,呵呵。 

好了,今天的內容就選到這里了。 
下載鏈接:http://tokyotyrantclient.codeplex.com/

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产乱码精品一区二区三区av | 黄a视频 | 四虎影视最新免费版 | 欧美一区二区三区不卡 | 亚洲精品无 | 日韩操操操 | 日韩成人 | 91精品国产九九九久久久亚洲 | 日韩在线一区二区 | 久久99精品久久久久久噜噜 | www久| 日韩和的一区二在线 | 午夜电影网址 | 国产成人a亚洲精品 | 中文精品在线 | 国产午夜精品一区二区三区免费 | av网站在线看 | 国产97在线 | 免费 | 毛片久久久 | 国产精品久久久91 | av在线天堂 | 98成人网| 懂色av中文字幕一区二区三区 | 男女激情网站 | 久久av网站 | 成人高清 | 这里只有精品在线 | 久久综合久色欧美综合狠狠 | 99精品免费视频 | 精品国产乱码久久久久久久 | 亚洲永久免费视频 | 久久九九这里只有精品 | 色九九 | 永久黄网站色视频免费观看w | 国产人成精品一区二区三 | 亚洲a网 | 亚洲成人免费 | 欧美精品成人 | 91精品国产91久久综合 | 国产精品网站在线观看 | 天天久久综合网 |