分布式緩存系統 Xixibase
Xixibase是一個高性能,跨平臺的分布式緩存系統。Xixibase server 采用 C++ 實現,底層網絡庫采用的是Boost Asio。
Xixibase 主要特點:
1. 實現'Local Cache'功能, 當客戶端打開'Local Cache'選項, 客戶端可以將數據同時存儲在Server 端和本地,并且保證本地數據和Server 端的數據的一致性。當Server 端的數據被更新、刪除或者過期,本地的數據會立即被刪除,下次再對該數據的訪問,請求會直接到達Server 。
'Local Cache'的優點:
a. 極大地提高了性能:特別是對那些讀操作遠遠大于寫操作的數據,可以提供1000萬以上的TPS.參考:http://xixibase.googlecode.com/svn/trunk/benchmark/java/benchmark2.html
b. 提高了應用的服務質量和用戶體驗:在'Local Cache'命中的情況下,請求不需要通過網絡到遠程Cache Server上查詢,減少了總體的處理的時間,提高用戶體驗。
c. 降低了Cache Server 的壓力,原先需要10臺Cache Server ,現在可能只要5臺就夠了。可降低成本,保護環境。
d. 降低網絡流量,減少網絡設備的成本。
e. 提高整個Cache 系統的總體吞吐量。綜合a, c, d三點,系統的總體吞吐量會得到極大的提升。
2. 支持虛擬化, 采用分Group的方法,不同的應用可以使用不同的GroupID,這樣當不同的應用在訪問同一個Cache Server時,不會相互干擾。
a. GroupID類似與命名空間,每個應用不需要考慮:某個Key 是否會和其它應用的Key 沖突。
b. 當某個應用要清空自己相關的Cache,不需要一個Key 一個Key 的去Delete ,可以直接調用Flush ,不用擔心Flush 會影響其它應用的數據。
c. 可以對每個Group 單獨統計讀寫、存儲的信息。
3. 支持'MultiAPI', 如multiGet, multeUpdate, multiDelete。測試表明'MultiAPI'在提升性能方面,非常明顯。參考:http://xixibase.googlecode.com/svn/trunk/benchmark/java/benchmark.html
4. 超高性能. 無論'Local Cache'還是'MultiAPI'都在不同方面,極大地提升了性能。
5. 跨平臺, Xixibase server由C++實現,底層網絡庫采用的是Boost Asio。理論上,只要Boost Asio支持的平臺,Xixibase server都可以支持。目前,已經測試了Linux, Windows, Mac。
性能:
讀寫TPS :150,000以上
啟動Local Cache高命中情況下,讀TPS:10,000,000以上。
MultiAPI, TPS: 不同條件下,差異較大,詳情參考一下鏈接:
1. 和Memcached的幾個Client 比較:
http://xixibase.googlecode.com/svn/trunk/benchmark/java/benchmark.html
2. Performance Benchmark:
http://xixibase.googlecode.com/svn/trunk/benchmark/java/benchmark2.html
項目:
http://code.google.com/p/xixibase/
包含:Xixibase Server 和Xixibase Java Client
目前Client 只實現了Java Client,歡迎有興趣的朋友可以實現其它平臺的Client。
關于Xixibase Java Client 的使用,test包里有幾個例子,大家可以參考一下。
有任何問題、建議或者發現Bug可以聯系本人。
Java客戶端示例:
/* Copyright [2011] [Yao Yuan(yeaya@163.com)]Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */
package com.xixibase.cache;
import java.util.ArrayList; import java.util.List;
import com.xixibase.cache.multi.MultiDeleteItem; import com.xixibase.cache.multi.MultiUpdateItem;
public class CacheClientBench { int start = 1; int runs = 50000; int groupID = 0; String keyBase = "keypublic CacheClientBench(String servers, int start, int runs, int groupID,"; String object = "value"; CacheClient cc;
public CacheClientBench(String servers, int start, int runs, int groupID, boolean consistentFlag, int hashingAlg, Integer[] weights) { this.start = start; this.runs = runs; this.groupID = groupID; String[] serverlist = servers.split(","); XixiWeightMap<Integer> weightMap = new XixiWeightMap<Integer>(consistentFlag, hashingAlg); CacheClientManager manager = CacheClientManager.getInstance("CacheClientBench"); manager.setInitConn(1); manager.setNoDelay(false); manager.initialize(serverlist, weights, weightMap); manager.enableLocalCache(); manager.getLocalCache().setMaxCacheSize(128 * 1024 * 1024); cc = manager.createClient(groupID); System.out.println("keybaselen=" + keyBase.length() + " objlen=" + object.length()); } public CacheClientBench(String servers, int start, int runs) { this(servers, start, runs, 0, false, XixiWeightMap.NATIVE_HASH, null); } public boolean runIt() { flush(); boolean ret = true; ret &= set(); ret &= getW(); ret &= getL(); ret &= multiGet(); ret &= delete(); ret &= multiSet(); ret &= multiGetForSet(); ret &= multiDelete(); ret &= multiSet(); ret &= flush(); CacheClientManager.getInstance("CacheClientBench").shutdown(); return ret; } boolean set() { boolean r = true; long begin = System.currentTimeMillis(); for (int i = start; i < start + runs; i++) { long ret = cc.set(keyBase + i, object); if (ret == 0) { r = false; System.out.println("set error index=" + i + " obj=" + object); } } long end = System.currentTimeMillis(); long time = end - begin; System.out.println(runs + " sets: " + time + "ms"); return r; } boolean getW() { boolean r = true; long begin = System.currentTimeMillis(); String obj = ""; for (int i = start; i < start + runs; i++) { obj = (String)cc.getW(keyBase + i); if (!object.equals(obj)) { r = false; System.out.println("getW error index=" + i + " obj=" + obj); } } long end = System.currentTimeMillis(); long time = end - begin; System.out.println(runs + " getW: " + time + "ms"); return r; } boolean getL() { boolean r = true; long begin = System.currentTimeMillis(); Object obj = ""; for (int i = start; i < start + runs; i++) { obj = (String)cc.getL(keyBase + i); if (!object.equals(obj)) { r = false; System.out.println("getL error index=" + i + " obj=" + obj); } } long end = System.currentTimeMillis(); long time = end - begin; System.out.println(runs + " getL: " + time + "ms"); return r; } boolean multiGet() { ArrayList<String> keys = new ArrayList<String>(runs); for (int i = start; i < start + runs; i++) { keys.add(keyBase + i); } long begin = System.currentTimeMillis(); List<CacheItem> m = cc.multiGet(keys); long end = System.currentTimeMillis(); long time = end - begin; int missCount = 0; for (int i = start; i < start + runs; i++) { String key = keyBase + i; if (m.get(i - start) == null) { System.out.println("can not find the key=" + key); missCount++; } } System.out.println(runs + " multiGet: " + time + "ms" + " count=" + m.size() + " missCount=" + missCount); return missCount == 0; } boolean multiSet() { ArrayList<MultiUpdateItem> items = new ArrayList<MultiUpdateItem>(runs); String value = object.toString() + 1; for (int i = start; i < start + runs; i++) { MultiUpdateItem item = new MultiUpdateItem(); items.add(item); item.key = keyBase + i; item.value = value; item.cacheID = 0; } long begin = System.currentTimeMillis(); int count = cc.multiSet(items); long end = System.currentTimeMillis(); long time = end - begin; int missCount = 0; for (int i = 0; i < items.size(); i++) { MultiUpdateItem item = items.get(i); if (item.getNewCacheID() == 0) { missCount++; } } System.out.println(runs + " multiSet: " + time + "ms" + " count=" + count + " missCount=" + missCount); return missCount == 0; } boolean multiGetForSet() { ArrayList<String> keys = new ArrayList<String>(runs); for (int i = start; i < start + runs; i++) { keys.add(keyBase + i); } long begin = System.currentTimeMillis(); List<CacheItem> items = cc.multiGet(keys); long end = System.currentTimeMillis(); long time = end - begin; int missCount = 0; String value = object.toString() + 1; for (int i = start; i < start + runs; i++) { String key = keyBase + i; CacheItem item = items.get(i - start); if (item == null || !item.getValue().equals(value)) { System.out.println("not key=" + key); missCount++; } } System.out.println(runs + " multiGetForSet: " + time + "ms" + " count=" + items.size() + " missCount=" + missCount); return missCount == 0; } boolean multiDelete() { ArrayList<MultiDeleteItem> items = new ArrayList<MultiDeleteItem>(runs); for (int i = start; i < start + runs; i++) { MultiDeleteItem item = new MultiDeleteItem(); items.add(item); item.key = keyBase + i; item.cacheID = 0; } long begin = System.currentTimeMillis(); int count = cc.multiDelete(items); long end = System.currentTimeMillis(); long time = end - begin; System.out.println(runs + " multiDelete: " + time + "ms" + " count=" + count); return true; } boolean delete() { long begin = System.currentTimeMillis(); for (int i = start; i < start + runs; i++) { cc.delete(keyBase + i); } long end = System.currentTimeMillis(); long time = end - begin; System.out.println(runs + " deletes: " + time + "ms"); return true; } boolean flush() { long begin = System.currentTimeMillis(); int count = cc.flush(); long end = System.currentTimeMillis(); long time = end - begin; System.out.println(runs + " flush: " + time + "ms" + " count=" + count); return count == runs; } public static void main(String[] args) { String servers = System.getProperty("hosts"); if (args.length >= 1) { servers = args[0]; } CacheClientBench bench = new CacheClientBench(servers, 1, 50000); bench.runIt(); }
}</pre>
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!