Embrace change, now also embarked on. Net/java take-all era, here is how to let. Net/java can access the Shard of Redis Bar.
There are several key points: consistency ring hash, hash algorithm, serialization, deserialization
The latter two are more straightforward, just choose a cross-language serialization approach, such as: JSON, PROTOBUF, ACE, etc., this article all slightly
This article is based on Jedis consistency ring hash modified,. NET selected is Servicestack.redis component to modify
Helpless two components have their own consistency ring hash algorithm, incompatible, then choose one as the standard, modify the other slightly. This article chooses Jedis's consistency ring hash as the standard, and modifies. NET to adapt to Jedis
The logic of Jedis is to construct 160 virtual nodes for each Redis node and put it into a binary tree (Key/value:key is a long value, a long is calculated based on the hash algorithm, and value is the node ID, which is a string).
OK, the logic is clear, it is simple, to the C # side write an identical consistency ring hash algorithm.
Public classsharded {Private ObjectNodes_lock =New Object(); Privateredblacktreemap<Long,string> nodes =Newredblacktreemap<Long,string>(); PrivateIhash Hashalgo =NewMd5_longsum_multiply_hash (); Public voidAddTarget (intIndexstringShard) { Lock(nodes_lock) { for(intn =0; N < the; ++N) {varHashKey ="shard-"+ Index +"-node-"+N; LongHashValue = This. Hashalgo.hash (HashKey); Nodes. Setoraddvalue (HashValue, Shard); } } } Public stringGetshardinfo (stringkey) { LongSearchhashkey = This. Hashalgo.hash (key); LongNearestkey; stringShard; Lock(nodes_lock) {if( This. Nodes. Nearestgreater (Searchhashkey, outNearestkey)) {Shard= This. Nodes. GetValue (Nearestkey); returnShard; } if( This. Nodes. Least ( outSearchhashkey, outshard)) returnShard; } Throw NewException ("Getshardinfo Exception"); } }
Where Redblacktreemap this is a component in treelib and needs to be referenced on NuGet.
Md5_longsum_multiply_hash, this is a MD5 algorithm, the input is a string, the output is a long.
This is because the output is not a string, so I changed it, let him output long
Public classMd5_longsum_multiply_hash:ihash { Public LongHash (stringkey) { varmd5=Md5hash (key); if(string. IsNullOrEmpty (MD5)) Log.getlog (). Info ("Hash, MD5 is null or empty"); varConvertedkeybytes =Encoding.UTF8.GetBytes (MD5); LongValue =1; foreach(varBinchconvertedkeybytes) Value*= b*-1; returnvalue; } Private stringMd5hash (stringinput) {MD5CryptoServiceProvider Md5hasher=NewMD5CryptoServiceProvider (); if(string. IsNullOrEmpty (input)) Log.getlog (). Info ("Md5hash, input is null or empty"); byte[] data =Md5hasher.computehash (Encoding.Default.GetBytes (input)); StringBuilder Sbuilder=NewStringBuilder (); for(inti =0; I < data. Length; i++) {sbuilder.append (Data[i]. ToString ("X2")); } returnsbuilder.tostring (); } }
The rest is the Java side of this input string, the output of long algorithm, and. NET need to be consistent with the input and output.
Then also write a hashing algorithm, let him input string, output long, and. NET consistent, here as long as java/.net with the same MD5 algorithm, the subsequent MD5 into a long is very easy.
ImportOrg.springframework.security.authentication.encoding.MessageDigestPasswordEncoder;Importredis.clients.util.Hashing;ImportRedis.clients.util.SafeEncoder;Importjava.io.UnsupportedEncodingException;/*** Created by Z on 2017/4/12.*/ Public classMd5_sum_hashImplementsHashing {Messagedigestpasswordencoder encoder=NewMessagedigestpasswordencoder ("MD5"); Public LongHash (String key) {return This. Hash (Safeencoder.encode (key)); } Public LongHashbyte[] bytes) {String Converted_str=NULL; Try{converted_str=NewString (Bytes, "UTF8"); } Catch(unsupportedencodingexception e) {e.printstacktrace (); The String result=encoder.encodepassword (CONVERTED_STR,NULL); Try{bytes=result.getbytes ("UTF8"); } Catch(unsupportedencodingexception e) {e.printstacktrace (); } LongValue = 1; for(byteb:bytes) Value*= b*-1; returnvalue; }}
< Dependency > < groupId >org.springframework.security</groupId> < Artifactid >spring-security-core</artifactid> </ Dependency >
OK, that's it for the core.
C # Servicestack.redis Interoperability Java Jedis