Make HashMod use MD5 instead of FNV

MD5 will will distribute the inputs more uniformly over the output
space than FNV; leading to more evenly balanced load when using HashMod.
This commit is contained in:
Miek Gieben 2015-08-12 15:44:42 +01:00
parent b5861b02ac
commit caaa3de4ff
2 changed files with 15 additions and 5 deletions

View File

@ -1,8 +1,8 @@
package retrieval package retrieval
import ( import (
"crypto/md5"
"fmt" "fmt"
"hash/fnv"
"strings" "strings"
clientmodel "github.com/prometheus/client_golang/model" clientmodel "github.com/prometheus/client_golang/model"
@ -58,12 +58,22 @@ func relabel(labels clientmodel.LabelSet, cfg *config.RelabelConfig) (clientmode
labels[cfg.TargetLabel] = clientmodel.LabelValue(res) labels[cfg.TargetLabel] = clientmodel.LabelValue(res)
} }
case config.RelabelHashMod: case config.RelabelHashMod:
hasher := fnv.New64a() mod := sum64(md5.Sum([]byte(val))) % cfg.Modulus
hasher.Write([]byte(val))
mod := hasher.Sum64() % cfg.Modulus
labels[cfg.TargetLabel] = clientmodel.LabelValue(fmt.Sprintf("%d", mod)) labels[cfg.TargetLabel] = clientmodel.LabelValue(fmt.Sprintf("%d", mod))
default: default:
panic(fmt.Errorf("retrieval.relabel: unknown relabel action type %q", cfg.Action)) panic(fmt.Errorf("retrieval.relabel: unknown relabel action type %q", cfg.Action))
} }
return labels, nil return labels, nil
} }
// sum64 sums the md5 hash to an uint64.
func sum64(hash [md5.Size]byte) uint64 {
var s uint64
for i, b := range hash {
shift := uint64((md5.Size - i - 1) * 8)
s |= uint64(b) << shift
}
return s
}

View File

@ -170,7 +170,7 @@ func TestRelabel(t *testing.T) {
"a": "foo", "a": "foo",
"b": "bar", "b": "bar",
"c": "baz", "c": "baz",
"d": "58", "d": "976",
}, },
}, },
} }