需求:
对数据库做一个哈希压缩吧,用数字指纹
看看go源码:
package main
import (
"fmt"
)
type Label struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
var (
labelsB = []*Label{
{Name: "__name__", Value: "http_requests_total"},
{Name: "code", Value: "200"},
{Name: "handler", Value: "query"},
}
expectedB = uint64(0x145426e4f81508d1)
)
const (
offset64 uint64 = 14695981039346656037
prime64 uint64 = 1099511628211
separatorByte byte = 255
)
// hashAdd adds a string to a fnv64a hash value, returning the updated hash.
func hashAdd(h uint64, s string) uint64 {
fmt.Println(len(s))
for i := 0; i < len(s); i++ {
fmt.Printf("%v\n",s[i])
h ^= uint64(s[i])
//fmt.Println(h)
h *= prime64
//fmt.Println(h)
}
return h
}
// hashAddByte adds a byte to a fnv64a hash value, returning the updated hash.
func hashAddByte(h uint64, b byte) uint64 {
h ^= uint64(b)
h *= prime64
return h
}
// Fingerprint calculates a fingerprint of SORTED BY NAME labels.
// It is adopted from labelSetToFingerprint, but avoids type conversions and memory allocations.
func Fingerprint(labels []*Label) uint64 {
if len(labels) == 0 {
return offset64
}
sum := offset64
for _, l := range labels {
println(l.Name, l.Value)
sum = hashAdd(sum, l.Name)
println(sum)
sum = hashAddByte(sum, separatorByte)
println(sum)
sum = hashAdd(sum, l.Value)
println(sum)
sum = hashAddByte(sum, separatorByte)
println(sum)
println()
}
return sum
}
func main() {
/*mylabel := []*Label{
{Name: "__name__", Value: "up"},
{Name: "instance", Value: "promhouse_clickhouse_exporter_1:9116"},
{Name: "job", Value: "clickhouse"},
}
fmt.Println(Fingerprint(mylabel))
*/
fmt.Println(hashAdd(offset64, "一体化"))
}
转成java
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
public class FingerPrint
{
private static final BigInteger offset64 = new BigInteger("14695981039346656037");
private static final BigInteger prime64 = new BigInteger("1099511628211");
private static final String separatorByte = "255";
private static Gson gson = new GsonBuilder().serializeNulls().create();
public static void main(String[] args)
{
//System.out.println(hashAdd(offset64, "__name__"));
//System.out.println(hashAdd(offset64, "一体化"));
}
public static BigInteger hashAdd(BigInteger h, String s)
{
String[] strings = s.split("");
for (int i=0; i<s.length(); i++)
{
//System.out.println(strings[i]);
//System.out.println(strings[i].getBytes().length);
//中文的编码有三位,逐位解析
for(byte b: strings[i].getBytes()) {
//System.out.println((b + 256) % 256);
//将中文编码变为正数
h = h.xor(BigInteger.valueOf((b + 256) % 256));
//根据go的uint64的限制进行mod
h = h.multiply(prime64).mod(new BigInteger("18446744073709551616"));
}
//h = h.xor(new BigInteger(strings[i].getBytes()));
//System.out.println(h);
//h = h.multiply(prime64).mod(new BigInteger("18446744073709551616"));
//System.out.println(h);
}
return h;
}
public static BigInteger hashAddByte(BigInteger h, String s)
{
h = h.xor(new BigInteger(s));
h = h.multiply(prime64).mod(new BigInteger("18446744073709551616"));
return h;
}
public static BigInteger fingerprint(JsonObject prometheusLabelJsonObject)
{
if (prometheusLabelJsonObject.size()==0)
{
return offset64;
}
else
{
BigInteger sum = new BigInteger(String.valueOf(offset64));
for(Map.Entry<String, JsonElement> entry : prometheusLabelJsonObject.entrySet())
{
//System.out.println(entry.getKey());
//System.out.println(entry.getValue().getAsString());
sum = hashAdd(sum, entry.getKey());
//System.out.println(sum);
sum = hashAddByte(sum, separatorByte);
//System.out.println(sum);
sum = hashAdd(sum, entry.getValue().getAsString());
//System.out.println(sum);
sum = hashAddByte(sum, separatorByte);
//System.out.println(sum);
//System.out.println();
}
return sum;
}
}
}
代码转换坑点:
1.java用大数
2.go uint64要除上界
3.go对中文的处理直接分三个ascii(0-256), java三合1还是负数,要变正数
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)