如何设计实现最基础的分布式应用,我们可以从如下两个ID入手:一个是全球唯一标识,另一个分布式hash散列值。
前一个保证你各个服务器之间产生的不通ID是不重复的,因为它的主要算法是跟时间和MAC地址有关的,后一个决定你
的数据是分发给哪台服务器处理。
对GUID不是太理解的可以看如下一段(摘抄自杂志):
UUID含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标准,也是被开源软件基金会 (Open Software Foundation, OSF) 的组织在分布式计算环境 (Distributed Computing Environment, DCE) 领域的一部份。UUID 的目的,是让分布式系统中的所有元素,都能有唯一的辨识资讯,而不需要透过中央控制端来做辨识资讯的指定。如此一来,每个人都可以建立不与其它人冲突的 UUID。在这样的情况下,就不需考虑数据库建立时的名称重复问题。目前最广泛应用的 UUID,即是微软的 Microsoft's Globally Unique Identifiers (GUIDs)。
一般我们在分布式系统中用guid做主键,而在列中增加一个 id_hash来保存期hash值。
一.guid 如何实现
JAVA uitil中采用了统一的实现,参看
System.out.println(UUID.randomUUID().toString());
结果
1a078dc9-df28-4841-ad7a-00214f8a5ea7
二.hash值如何实现。
/** * * @param str 需要散列的字符串 * @param mode 散列度 * @return */ public static int getStringHashValue(String str,int mode){ Assert.notNull(str,"the hashString must not be null"); int val=str.hashCode(); if(val==Integer.MIN_VALUE) return 0;//处理当hashCode返回MIN_VALUE,abs为负的情况 return Math.abs(val)%mode; };
System.out.println("the string 'abc' hash value = "+getStringHashValue("abc",mode)); System.out.println("the string 'abc' hash value = "+getStringHashValue("abc",mode));
结果:
the string 'abc' hash value = 303 the string 'abc' hash value = 303
上面可以看到,满足一致性规则,相同的string产生了相同的hash值,这就保证了相同ID的用户分布到相同的机器上,满足了不同用户数据的隔离。
三.不同线程取数据如何隔离
通过hashStart 和 hashEnd 来分段取数据。例如:
searchParams.put("hashStart", profile.getHashStart()); searchParams.put("hashEnd", profile.getHashEnd()); searchParams.put("total", threadDataTotalInt); searchParams.put("collectType", BillingConstants.COLLECT_TYPE_INC); List<BillingCollectBean> collects = billingCollectService.getIncCollectBeans(searchParams);
profile.getHashStart()和profile.getHashEnd()通过antx配置,不同的机器配置不同的hash区段。
为满足平行扩展,我们最好将这些信息配置在数据库,通过读取数据库,自动取到自己的机器到底该处理哪些区段的纪录,
hash值散列时,mod取值可以根据机器数量和数据数进行设置,最好取的大一点,这样可以保证散列的均匀,同时粒度变的细小也便于控制(如果只有2,那最多可以给两个机器使用)。我们系统目前设置为1000。