分析Memcached客户端如何把缓存数据分布到多个服务器上
Memcached客户端可以设多个memcached服务器,它是如何把数据分发到各个服务器上,而使各个服务器负载平衡的呢?
可以看看.net版中的客户端中的源码,就可以知道 先看代码:
1 /// <summary>
2 /// Returns appropriate SockIO object given
3 /// string cache key and optional hashcode.
4 ///
5 /// Trys to get SockIO from pool. Fails over
6 /// to additional pools in event of server failure.
7 /// </summary>
8 /// <param name="key">hashcode for cache key</param>
9 /// <param name="hashCode">if not null, then the int hashcode to use</param>
10 /// <returns>SockIO obj connected to server</returns>
11 public SockIO GetSock(string key, object hashCode)
12 {
13 string hashCodeString = "<null>";
14 if(hashCode != null)
15 hashCodeString = hashCode.ToString();
16
17 if(Log.IsDebugEnabled)
18 {
19 Log.Debug(GetLocalizedString("cache socket pick").Replace("$$Key$$", key).Replace("$$HashCode$$", hashCodeString));
20 }
21
22 if (key == null || key.Length == 0)
23 {
24 if(Log.IsDebugEnabled)
25 {
26 Log.Debug(GetLocalizedString("null key"));
27 }
28 return null;
29 }
30
31 if(!_initialized)
32 {
33 if(Log.IsErrorEnabled)
34 {
35 Log.Error(GetLocalizedString("get socket from uninitialized pool"));
36 }
37 return null;
38 }
39
40 // if no servers return null
41 if(_buckets.Count == 0)
42 return null;
43
44 // if only one server, return it
45 if(_buckets.Count == 1)
46 return GetConnection((string)_buckets[0]);
47
48 int tries = 0;
49
50 // generate hashcode
51 int hv;
52 if(hashCode != null)
53 {
54 hv = (int)hashCode;
55 }
56 else
57 {
58
59 // NATIVE_HASH = 0
60 // OLD_COMPAT_HASH = 1
61 // NEW_COMPAT_HASH = 2
62 switch(_hashingAlgorithm)
63 {
64 case HashingAlgorithm.Native:
65 hv = key.GetHashCode();
66 break;
67
68 case HashingAlgorithm.OldCompatibleHash:
69 hv = OriginalHashingAlgorithm(key);
70 break;
71
72 case HashingAlgorithm.NewCompatibleHash:
73 hv = NewHashingAlgorithm(key);
74 break;
75
76 default:
77 // use the native hash as a default
78 hv = key.GetHashCode();
79 _hashingAlgorithm = HashingAlgorithm.Native;
80 break;
81 }
82 }
83
84 // keep trying different servers until we find one
85 while(tries++ <= _buckets.Count)
86 {
87 // get bucket using hashcode
88 // get one from factory
89 int bucket = hv % _buckets.Count;
90 if(bucket < 0)
91 bucket += _buckets.Count;
92
93 SockIO sock = GetConnection((string)_buckets[bucket]);
94
95 if(Log.IsDebugEnabled)
96 {
97 Log.Debug(GetLocalizedString("cache choose").Replace("$$Bucket$$", _buckets[bucket].ToString()).Replace("$$Key$$", key));
98 }
99
100 if(sock != null)
101 return sock;
102
103 // if we do not want to failover, then bail here
104 if(!_failover)
105 return null;
106
107 // if we failed to get a socket from this server
108 // then we try again by adding an incrementer to the
109 // current key and then rehashing
110 switch(_hashingAlgorithm)
111 {
112 case HashingAlgorithm.Native:
113 hv += ((string)("" + tries + key)).GetHashCode();
114 break;
115
116 case HashingAlgorithm.OldCompatibleHash:
117 hv += OriginalHashingAlgorithm("" + tries + key);
118 break;
119
120 case HashingAlgorithm.NewCompatibleHash:
121 hv += NewHashingAlgorithm("" + tries + key);
122 break;
123
124 default:
125 // use the native hash as a default
126 hv += ((string)("" + tries + key)).GetHashCode();
127 _hashingAlgorithm = HashingAlgorithm.Native;
128 break;
129 }
130 }
131
132 return null;
133 }
134
上面代码是代码文件SockIOPool.cs中的一个方法,从方法签名上可以看出,获取一个socket连接是根据需要缓存数据的唯一键和它的哈希值,因为缓存的数据的键值是唯一的,所以它的哈希代码也是唯一的;
再看看上面方法中的以下代码:
int bucket = hv % _buckets.Count;
if(bucket < 0)
bucket += _buckets.Count;
SockIO sock = GetConnection((string)_buckets[bucket]);
具体的选择服务器的算法是:唯一键值的哈希值与存放服务器列表中服务器(服务器地址记录不是唯一的)的数量进行模数运算来选择服务器的地址的。所以数据缓存在那台服务器取决于缓存数据的唯一键值所产生的哈希值和存放服务器列表中服务器的数量值,所以访问memcached服务的所有客户端操作数据时都必须使用同一种哈希算法和相同的服务器列表配置,否则就会或取不到数据或者重复存取数据。由于不同数据的唯一键所对应的哈希值不同,所以不同的数据就有可能分散到不同的服务器上,达到多个服务器负载平衡的目的。
如果几台服务器当中,负载能力各不同,想根据具体情况来配置各个服务器负载作用,也是可以做到的。看上面代码,可以知道程序是从_buckets中获取得服务器地址的,_buckets存放着服务器的地址信息,服务器地址在_bucket列表中并不是唯一的,它是可以有重复记录的。相同的服务器地址在_bucket重复记录越多,它被选中的机率就越大,相应负载作用也就越大。
怎么设置服务器让它发挥更大的负载作用,如下面代码:
String[] serverlist = {"192.168.1.2:11211", "192.168.1.3:11211"};
int[] weights = new int[]{5, 2};
SockIOPool pool = SockIOPool.GetInstance();
pool.SetServers(serverlist);
pool.SetWeights(weights);
pool.Initialize();
pool.SetWeights(weights)方法就是设配各个服务器负载作用的系数,系数值越大,其负载作用也就越大。如上面的例子,就设服务器192.168.1.2的负载系数为5,服务器192.168.1.3的负载系数为2,也就说服务器192.168.1.2 比192.168.1.3的负载作用大。
程序中根据缓存数据中的唯一
键标识的哈希值跟服务器列表中服务器记录数量求模运算来确定数据的缓存的位置的方法,算法的优点:能够把数据匀均的分散到各个服务器上数据服务器负载平
衡,当然也可以通过配置使不同服务器有不同的负载作用。但也有缺点:使同类的数据过于分散,同个模块的数据都分散到不同的数据,不好统一管理和唯护;比
如:现在有A、B、C、D四台服务器一起来做缓存服务器,数月后C台服务器突然死掉不可用啦,那么按算法缓存在C台服务器的数据都不可用啦,但客户端还是按原来的四台服务器的算法来取操作数据,所以分布在C服务上的数据在C服务器恢复可用之前都不可用,都必须从数据库中读取数据,并且不能添加到缓存中,因为只要缓存数据的Key不变,它还是会被计算分配到C服务器上。如果想把分配到C服务器就必须全部初始化A、B、D三台服务器上的所有数据,并把C服务器从服务器列表中移除。
如果我们能够把数据分类分布到各个服务器中,同类型的数据分布到相同的服务器;比如说,A服务器存放用户日志模块信息,B服务器存放用户相册模块信息,C服务器存放音乐模块信息,D服务器存放用户基础信息。如果C服务器不可用后,就可以更改下配置使它存放在其它服务器当中,而且并不影响其它服务器的缓存信息。
解决方法1:不同的模块使用不同memcached客户端实例,这样不同模块就可以配置不同的服务器列表,这样不同模块的数据就缓存到了不同的服务器中。这样,当某台服务器不可用后,只会影响到相应memcached客户端实例的数据,而不会影响到其它客户端实例的数据。
解决方法2:修改或添加新的算法,并在数据唯一键中添加命名空间,算法根据配置和数据唯一键中命名空间来选择不同的Socket连接,也就是服务器啦。
数据项唯一键(key)的定义:命名空间.数据项ID,就跟编程中的” 命名空间”一样,经如说用户有一篇日志的ID是”999999”, 那么这条篇日志的唯一键就是:Sns.UserLogs.Log.999999,当然我们存贮的时候考虑性能问题,可以用一个短的数值来代替命名空间。这样在选择Socket的时候就可以根据数据项中的唯一键来选择啦。
分析Memcached客户端如何把缓存数据分布到多个服务器上的更多相关文章
- php memcache 缓存与memcached 客户端的详细步骤
缓存服务器有Memcache.Redis,我主要介绍了PHP中的Memcache,从Memcache简介开始,详细讲解了如Memcache和memcached的区别.PHP的 Memcache所有操作 ...
- 详细分析Memcached缓存与Mongodb数据库的优点与作用
http://www.mini188.com/showtopic-1604.aspx 本文详细讲下Memcached和Mongodb一些看法,以及结合应用有什么好处,希望看到大家的意见和补充. Mem ...
- ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存
ASP.Net MVC4+Memcached+CodeFirst实现分布式缓存 part 1:给我点时间,允许我感慨一下2016年 正好有时间,总结一下最近使用的一些技术,也算是为2016年画上一个完 ...
- memcached客户端的使用
一. 概念 Memcached是danga.com(运营LiveJournal的技术团队)开发的一套分布式内存对象缓存系统,用于在动态系统中减少数据库负载,提升性能. 二. 适用场合 1. 分布式应用 ...
- Windows下Memcached在.Net程序中的实际运用(从Memcached客户端Enyim的库的编译到实际项目运用)
1.一点基础概念 2.获取EnyimMemcached客户端的源代码并编译出动态库 3.Memcached的服务器安装(windows server) 4.在web项目中实战 一.基础概念 memca ...
- Memcached源代码分析 - Memcached源代码分析之消息回应(3)
文章列表: <Memcached源代码分析 - Memcached源代码分析之基于Libevent的网络模型(1)> <Memcached源代码分析 - Memcached源代码分析 ...
- Python并发编程-Memcached (分布式内存对象缓存系统)
一.Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的 ...
- Spring学习(六)——集成memcached客户端
memcached是高性能的分布式内存缓存服务器.许多Web应用都将数据保存到RDBMS中,应用服务器从中读取数据并在浏览器中显示. 但随着数据量的增大.访问的集中,就会出现RDBMS的负担加重.数据 ...
- Hadoop源码分析之客户端向HDFS写数据
转自:http://www.tuicool.com/articles/neUrmu 在上一篇博文中分析了客户端从HDFS读取数据的过程,下面来看看客户端是怎么样向HDFS写数据的,下面的代码将本地文件 ...
随机推荐
- Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算
中缀表达式与后缀表达式的转换和计算 目录 中缀表达式转换为后缀表达式 后缀表达式的计算 1 中缀表达式转换为后缀表达式 中缀表达式转换为后缀表达式的实现方式为: 依次获取中缀表达式的元素, 若元素为操 ...
- SpringBoot事物管理器
一.springboot整合事物管理 springboot默认集成事物,只主要在方法上加上@Transactional即可 二.SpringBoot分布式事物管理 使用springboot+jta+a ...
- 洛谷——P2862 [USACO06JAN]把牛Corral the Cows
P2862 [USACO06JAN]把牛Corral the Cows 题目描述 Farmer John wishes to build a corral for his cows. Being fi ...
- [Lydsy1710月赛] 小B的数字
神TM 又又又又是构造题..... 很简单的化简就是,把2^k[i]都换成k[i] ,然后就可以得出 对于任意的i,k[i] * a[i] >= ∑k[]. 最优的构造肯定是使 k[i] = ...
- [BZOJ4398]福慧双修/[BZOJ2407]探险
题目大意: 给定一个$n(n\leq40000)$个点$m(m\leq100000)$条边的有向图,求从$1$出发回到$1$的不经过重复结点的最短路. 思路: 首先Dijkstra求出从1出发到每个结 ...
- Flash 3D学习计划
1.理解并记住3D渲染的一般管线流程(一天). 2.理解世界,取景,投影变换,并理解投影坐标系(一天). 3.学习VB,IB相关,理解三角形顶点顺序:在屏幕上显示2D矩形,并实现缩放,平移,旋转(三天 ...
- mysql truncate drop delete的区别
以下讨论,针对于mysql数据库. 为什么会想到这个问题呢? 因为项目中需要清除数据库的数据,而且需要实现自增的主键从0开始计数.所以想到总结一个几个常用的删除语法的差异. 可以做一个测试 建一个带有 ...
- Git历险记(一)
[编者按]作为分布式版本控制系统的重要代表——Git已经为越来越多的人所认识,它相对于我们熟悉的CVS.SVN甚至同时分布式控制系统的 Mercurial,有哪些优势和不足呢.这次InfoQ中文站有幸 ...
- yarn Fairscheduler与Capacityscheduler
Capacityscheduler Capacityscheduler允许多个组织共享整个集群,每个组织可以获得集群的一部分计算能力.通过为每个组织分配专门的队列,然后再为每个队列分配一定的集群资源, ...
- 【Eclipse】Eclipse 中 使用 Git 方法
参考资料: Eclipse关联GitHub实现版本控制:http://jingyan.baidu.com/article/64d05a0262f013de55f73bcc.html http://ww ...