2011-06-29 45 views
0

我用ehcache-spring-annotations使用了ehcache。 第一次,我們選擇HashCodeCacheKeyGenerator。這很不錯。 但1個月前我們發現「密鑰重複」。 所以我們用StringCacheKeyGenerator替換了HashCodeCacheKeyGenerator。 「密鑰重複」問題消失了,但是巨大的toString(使用apache ToStringBuilder)密鑰分配了堆內存(大約200M) 因爲參數對象(值對象)有巨大的字段。作爲ehcache密鑰的最短toString

我做了非常非常簡單的toString像下面

VerySimpleToStringStyle$Ta,,,,,1|2|3,1|2|3,a|b|c,true|false,64|65|66,1.0|2.0|3.0,1.0|2.0|3.0,,,,,,,1|2|3,[a, b, c],{b=2, c=3, a=1},a|1|false|{b=2, c=3, a=1}|[a, b, c],A,[b, c, a],,, 

正如你所看到的,沒有字段名,如果該值爲null沒有價值。 我希望使用SHA256,MD5哈希關於原始toString,但同事和我擔心「密鑰重複」。

任何想法最短toString方法的巨大值對象作爲ehcache鍵?

import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.List; 
import java.util.Map; 
import java.util.Set; 

import org.apache.commons.lang.builder.ToStringBuilder; 
import org.apache.commons.lang.builder.ToStringStyle; 

public class VerySimpleToStringStyle extends ToStringStyle { 
private static final long serialVersionUID = -8388711512639784062L; 

public VerySimpleToStringStyle() { 
    super(); 
    this.setUseClassName(true); 
    this.setUseIdentityHashCode(false); 
    this.setUseFieldNames(false); 
    this.setContentStart(""); 
    this.setContentEnd(""); 
    this.setNullText(""); 

    this.setFieldSeparatorAtStart(false); 
    this.setFieldSeparator(","); 
    this.setFieldSeparatorAtEnd(false); 

    this.setArrayStart(""); 
    this.setArraySeparator("|"); 
    this.setArrayEnd(""); 

} 

private static class T { 
    private String a = "a"; 
    private String a1 = null; 
    private String cc1; 
    private String cc2; 
    private String cc3; 
    private int[] i = new int[] {1, 2, 3}; 
    private long[] l = new long[] {1, 2, 3}; 
    private char[] c = new char[] {'a', 'b', 'c'}; 
    private boolean[] bl = new boolean[] {true, false}; 
    private byte[] b = new byte[] {64, 65, 66}; 
    private float[] f = new float[] {1, 2, 3}; 
    private double[] d = new double[] {1, 2, 3}; 
    private String bb1; 
    private String bb2; 
    private String bb3; 
    private String bb4; 
    private String bb5; 
    private String bb6; 
    private short[] s = new short[] {1, 2, 3}; 
    private List<String> list = new ArrayList<String>(); 
    private Map<String, String> m = new HashMap<String, String>(); 
    private Object[] o = new Object[] {"a", 1, false, m, list}; 
    private enum E {A, B, C}; 
    private E e = E.A; 
    private static String x = "x"; 
    private transient String y = "y"; 
    private Set<String> set = new HashSet<String>(); 
    private String aa1; 
    private String aa2; 
    private String aa3; 

    public T() { 
     this.list.add("a"); 
     this.list.add("b"); 
     this.list.add("c"); 

     this.m.put("a", "1"); 
     this.m.put("b", "2"); 
     this.m.put("c", "3"); 

     this.set.add("a"); 
     this.set.add("b"); 
     this.set.add("c"); 
    } 
} 

public static void main(String[] args) { 
    System.out.println(ToStringBuilder.reflectionToString(new T(), new VerySimpleToStringStyle())); 
} 
} 

回答

0

像sha256和MD5這樣的散列函數大多會很好。重複密鑰問題通常被稱爲關鍵衝突。絕對沒有辦法確保碰撞不會發生,因爲哈希函數會產生有限的可能性。散列函數的質量會使碰撞的可能性降低,但並非不可能。

爲了確保碰撞永遠不會發生但減小了生成的密鑰的大小,您可以做的是最大限度地使用這些值生成的密鑰中的entropy。簡而言之,使用壓縮函數是關鍵。然而,就你的情況而言,toString構建器似乎已經獲取了有關該對象的所有信息以構建密鑰,這違背了將緩存作爲已擁有所需信息的密鑰的目的。相反,密鑰應該是您嘗試緩存的對象的某種唯一標識符。

首先,確定什麼可以用作唯一標識符,因爲密鑰比如何生成密鑰更重要。

並找出處理碰撞的方法。

相關問題