當前位置:
首頁 > 知識 > C# servicestack.redis 互通 java jedis

C# servicestack.redis 互通 java jedis

擁抱變化,如今也走上了.net/java通吃的時代,下面就講講如何讓.net/java都能正常訪問分片的redis吧。

有幾個關鍵點:一致性環哈希、哈希演算法、序列化、反序列化

後兩個都比較直接,只要選擇一種跨語言的序列化方式就行了,如:json, protobuf, ace等,本文全略了

本文是基於jedis的一致性環哈希來修改的,.net選的是servicestack.redis組件來修改

無奈兩個組件都有各自的一致性環哈希演算法,不兼容,那就選一個作為標準,修改另一個咯。本文選擇jedis的一致性環哈希作為標準,進而修改.net來適應jedis

jedis的邏輯是給每個redis節點構造160個虛擬節點,放入一顆二叉樹中(key/value:key是一個long值,根據哈希演算法算出來的一個long、value是節點id,是個string)。

OK,邏輯清楚了,那就簡單了,給c#端寫個一模一樣的一致性環哈希演算法。

public class Sharded
{
private object nodes_lock = new object;
private RedBlackTreeMap nodes = new RedBlackTreeMap;
private IHash hashAlgo = new MD5_LongSUM_Multiply_Hash;

public void AddTarget(int index, string shard)
{
lock (nodes_lock)
{
for (int n = 0; n < 160; ++n) { var hashKey = "SHARD-" + index + "-NODE-" + n; long hashValue = this.hashAlgo.Hash(hashKey); nodes.SetOrAddValue(hashValue, shard); } } } public string GetShardInfo(string key) { long searchHashKey = this.hashAlgo.Hash(key); long nearestKey; string shard; lock (nodes_lock) { if (this.nodes.NearestGreater(searchHashKey, out nearestKey)) { shard = this.nodes.GetValue(nearestKey); return shard; } if (this.nodes.Least(out searchHashKey, out shard)) return shard; } throw new Exception("GetShardInfo exception"); } }

其中RedBlackTreeMap這個是TreeLib中的組件,需要在nuget上引用。

C# servicestack.redis 互通 java jedis

public class MD5_LongSUM_Multiply_Hash : IHash
{
public long Hash(string key)
{
var md5= Md5Hash(key);

if (string.IsNullOrEmpty(md5))
Log.GetLog.Info("Hash, md5 is null or empty");

var convertedKeyBytes = Encoding.UTF8.GetBytes(md5);

long value = 1;

foreach(var b in convertedKeyBytes)
value *= b*-1;

return value;
}

private string Md5Hash(string input)
{
MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider;

if (string.IsNullOrEmpty(input))
Log.GetLog.Info("Md5Hash, input is null or empty");

byte data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
StringBuilder sBuilder = new StringBuilder;
for (int i = 0; i < data.Length; i++) { sBuilder.Append(data[i].ToString("x2")); } return sBuilder.ToString; } }

剩下的就是java端的這個輸入string,輸出long的演算法,需要和.net的輸入輸出一致了。

那就也寫一個哈希演算法,讓他輸入string,輸出long,和.net的一致,這裡只要java/.net用同一種md5演算法,後續的md5變成long就很容易了。

import org.springframework.security.authentication.encoding.MessageDigestPasswordEncoder;
import redis.clients.util.Hashing;
import redis.clients.util.SafeEncoder;

import java.io.UnsupportedEncodingException;

/**
* Created by z on 2017/4/12.
*/
public class MD5_SUM_Hash implements Hashing {

MessageDigestPasswordEncoder encoder=new MessageDigestPasswordEncoder("MD5");

public long hash(String key) {
return this.hash(SafeEncoder.encode(key));
}

public long hash(byte[] bytes) {

String converted_str= null;
try {
converted_str = new String(bytes, "UTF8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace;
}

String result=encoder.encodePassword(converted_str, null);

try {
bytes=result.getBytes("UTF8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace;
}

long value = 1;
for(byte b : bytes)
value *= b*-1;
return value;
}
}


org.springframework.security
spring-security-core

OK,核心的就這些了。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 科技優家 的精彩文章:

BinarySearchTree-二叉搜索樹
Facebook開源Zstandard新型壓縮演算法代替Zlib 簡單使用
大數據操作:刪除和去重
Redis可視化工具Redis Desktop Manager使用
文件描述符與FILE

TAG:科技優家 |

您可能感興趣

教你如何開發不可檢測的C#、C++反向Shell
如何利用 C# 爬取「貓眼電影專業版:票房」數據!
看完這篇,終於知道自己會不會 C# 泛型了