- 浏览: 1017243 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (826)
- 硬件 (8)
- 软件 (24)
- 软件工程 (34)
- JAVA (229)
- C/C++/C# (77)
- JavaScript (8)
- PHP (1)
- Ruby (3)
- MySQL (14)
- 数据库 (19)
- 心情记事 (12)
- 团队管理 (19)
- Hadoop (1)
- spring (22)
- mybatis(ibatis) (7)
- tomcat (16)
- velocity (0)
- 系统架构 (6)
- JMX (8)
- proxool (1)
- 开发工具 (16)
- python (10)
- JVM (27)
- servlet (5)
- JMS (26)
- ant (2)
- 设计模式 (5)
- 智力题 (2)
- 面试题收集 (1)
- 孙子兵法 (16)
- 测试 (1)
- 数据结构 (7)
- 算法 (22)
- Android (11)
- 汽车驾驶 (1)
- lucene (1)
- memcache (12)
- 技术架构 (7)
- OTP-Erlang (7)
- memcached (17)
- redis (20)
- 浏览器插件 (3)
- sqlite (3)
- Heritrix (9)
- Java线程 (1)
- scala (0)
- Mina (6)
- 汇编 (2)
- Netty (15)
- libevent (0)
- CentOS (12)
- mongod (5)
- mac os (0)
最新评论
-
kingasdfg:
你这里面存在一个错误添加多个任务 应该是这样的 /** * ...
Quartz的任务的临时启动和暂停和恢复【转】 -
kyzeng:
纠正一个错误,long型对应的符号是J,不是L。
Jni中C++和Java的参数传递 -
zhaohaolin:
抱歉,兄弟,只是留下作记录,方便学习,如果觉得资料不好,可以到 ...
netty的个人使用心得【转】 -
cccoooccooco:
谢谢!自己一直以为虚机得使用网线才可以与主机连接呢。。
主机网卡无网线连接与虚拟机通信 -
yuqilin001:
要转别人的东西,请转清楚点嘛,少了这么多类,误人子弟
netty的个人使用心得【转】
◎Memcached的理论参数计算方式
影响 memcached 工作的几个参数有:
常量REALTIME_MAXDELTA 60*60*24*30
最大30天的过期时间
conn_init()中的freetotal(=200)
最大同时连接数
常量KEY_MAX_LENGTH 250
最大键长
settings.factor(=1.25)
factor将影响chunk的步进大小
settings.maxconns(=1024)
最大软连接
settings.chunk_size(=48)
一个保守估计的key+value长度,用来生成id1中的chunk长度(1.2)。id1的chunk长度等于这个数值加上item结构体的长度(32),即默认的80字节。
常量POWER_SMALLEST 1
最小classid(1.2)
常量POWER_LARGEST 200
最大classid(1.2)
常量POWER_BLOCK 1048576
默认slab大小
常量CHUNK_ALIGN_BYTES (sizeof(void *))
保证chunk大小是这个数值的整数倍,防止越界(void *的长度在不同系统上不一样,在标准32位系统上是4)
常量ITEM_UPDATE_INTERVAL 60
队列刷新间隔
常量LARGEST_ID 255
最大item链表数(这个值不能比最大的classid小)
变量hashpower(在1.1中是常量HASHPOWER)
决定hashtable的大小
根据上面介绍的内容及参数设定,可以计算出的一些结果:
1、在memcached中可以保存的item个数是没有软件上限的,之前我的100万的说法是错误的。
2、假设NewHash算法碰撞均匀,查找item的循环次数是item总数除以hashtable大小(由hashpower决定),是线性的。
3、Memcached限制了可以接受的最大item是1MB,大于1MB的数据不予理会。
4、Memcached的空间利用率和数据特性有很大的关系,又与DONT_PREALLOC_SLABS常量有关。 在最差情况下,有198个slab会被浪费(所有item都集中在一个slab中,199个id全部分配满)。
◎Memcached的定长优化
根据上面几节的描述,多少对memcached有了一个比较深入的认识。在深入认识的基础上才好对它进行优化。
Memcached本身是为变长数据设计的,根据数据特性,可以说它是“面向大众”的设计,但是很多时候,我们的数据并不是这样的“普遍”,典型的情况
中,一种是非均匀分布,即数据长度集中在几个区域内(如保存用户
Session);另一种更极端的状态是等长数据(如定长键值,定长数据,多见于访问、在线统计或执行锁)。
这里主要研究一下定长数据的优化方案(1.2),集中分布的变长数据仅供参考,实现起来也很容易。
解决定长数据,首先需要解决的是slab的分配问题,第一个需要确认的是我们不需要那么多不同chunk长度的slab,为了最大限度地利用资源,最好chunk和item等长,所以首先要计算item长度。
在之前已经有了计算item长度的算法,需要注意的是,除了字符串长度外,还要加上item结构的长度32字节。
假设我们已经计算出需要保存200字节的等长数据。
接下来是要修改slab的classid和chunk长度的关系。在原始版本中,chunk长度和classid是有对应关系的,现在如果把所有的
chunk都定为200个字节,那么这个关系就不存在了,我们需要重新确定这二者的关系。一种方法是,整个存储结构只使用一个固定的id,即只使用199
个槽中的1个,在这种条件下,就一定要定义DONT_PREALLOC_SLABS来避免另外的预分配浪费。另一种方法是建立一个hash关系,来从
item确定classid,不能使用长度来做键,可以使用key的NewHash结果等不定数据,或者直接根据key来做hash(定长数据的key也
一定等长)。这里简单起见,选择第一种方法,这种方法的不足之处在于只使用一个id,在数据量非常大的情况下,slab链会很长(因为所有数据都挤在一条
链上了),遍历起来的代价比较高。
前面介绍了三种空间冗余,设置chunk长度等于item长度,解决了第一种空间浪费问题,不预申请空间解决了第二种空间浪费问题,那么对于第一种问题
(slab内剩余)如何解决呢,这就需要修改POWER_BLOCK常量,使得每一个slab大小正好等于chunk长度的整数倍,这样一个slab就可
以正好划分成n个chunk。这个数值应该比较接近1MB,过大的话同样会造成冗余,过小的话会造成次数过多的alloc,根据chunk长度为200,
选择1000000作为POWER_BLOCK的值,这样一个slab就是100万字节,不是1048576。三个冗余问题都解决了,空间利用率会大大提
升。
修改 slabs_clsid 函数,让它直接返回一个定值(比如 1 ):
CODE:
unsigned int slabs_clsid(size_t size) {
return 1; } |
修改slabs_init函数,去掉循环创建所有classid属性的部分,直接添加slabclass[1]:
CODE:
slabclass[1].size = 200; //每chunk200字节
slabclass[1].perslab = 5000; //1000000/200 |
◎Memcached客户端
Memcached是一个服务程序,使用的时候可以根据它的协议,连接到memcached服务器上,发送命令给服务进程,就可以操作上面的数据。为了方
便使用,memcached有很多个客户端程序可以使用,对应于各种语言,有各种语言的客户端。基于C语言的有libmemcache、
APR_Memcache;基于Perl的有Cache::Memcached;另外还有Python、Ruby、Java、C#等语言的支持。PHP的
客户端是最多的,不光有mcache和PECL
memcache两个扩展,还有大把的由PHP编写的封装类,下面介绍一下在PHP中使用memcached的方法:
mcache扩展是基于libmemcache再封装的。libmemcache一直没有发布stable版本,目前版本是1.4.0-rc2,可以在这
里找到。libmemcache有一个很不好的特性,就是会向stderr写很多错误信息,一般的,作为lib使用的时候,stderr一般都会被定向到
其它地方,比如Apache的错误日志,而且libmemcache会自杀,可能会导致异常,不过它的性能还是很好的。
mcache扩展最后更新到1.2.0-beta10,作者大概是离职了,不光停止更新,连网站也打不开了(~_~),只能到其它地方去获取这个不负责的
扩展了。解压后安装方法如常:phpize & configure & make & make
install,一定要先安装libmemcache。使用这个扩展很简单:
[php]
<?php
$mc = memcache(); // 创建一个memcache连接对象,注意这里不是用new!
$mc->add_server('localhost', 11211); // 添加一个服务进程
$mc->add_server('localhost', 11212); // 添加第二个服务进程
$mc->set('key1', 'Hello'); // 写入key1 => Hello
$mc->set('key2', 'World', 10); // 写入key2 => World,10秒过期
$mc->set('arr1', array('Hello', 'World')); // 写入一个数组
$key1 = $mc->get('key1'); // 获取'key1'的值,赋给$key1
$key2 = $mc->get('key2'); // 获取'key2'的值,赋给$key2,如果超过10秒,就取不到了
$arr1 = $mc->get('arr1'); // 获取'arr1'数组
$mc->delete('arr1'); // 删除'arr1'
$mc->flush_all(); // 删掉所有数据
$stats = $mc->stats(); // 获取服务器信息
var_dump($stats); // 服务器信息是一个数组
?>
[/php]
这个扩展的好处是可以很方便地实现分布式存储和负载均衡,因为它可以添加多个服务地址,数据在保存的时候是会根据hash结果定位到某台服务器上的,这也
是libmemcache的特性。libmemcache支持集中hash方式,包括CRC32、ELF和Perl hash。
PECL memcache是PECL发布的扩展,目前最新版本是2.1.0,可以在pecl网站得到。memcache扩展的使用方法可以在新一些的PHP手册中找到,它和mcache很像,真的很像:
[php]
<?php
$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");
$version = $memcache->getVersion();
echo "Server's version: ".$version."\n";
$tmp_object = new stdClass;
$tmp_object->str_attr = 'test';
$tmp_object->int_attr = 123;
$memcache->set('key', $tmp_object, false, 10) or die ("Failed to save data at the server");
echo "Store data in the cache (data will expire in 10 seconds)\n";
$get_result = $memcache->get('key');
echo "Data from the cache:\n";
var_dump($get_result);
?>
[/php]
这个扩展是使用php的stream直接连接memcached服务器并通过socket发送命令的。它不像libmemcache那样完善,也不支持
add_server这种分布操作,但是因为它不依赖其它的外界程序,兼容性要好一些,也比较稳定。至于效率,差别不是很大。
另外,有很多的PHP class可以使用,比如MemcacheClient.inc.php,phpclasses.org上可以找到很多,一般都是对perl client API的再封装,使用方式很像。
◎BSM_Memcache
从C
client来说,APR_Memcache是一个很成熟很稳定的client程序,支持线程锁和原子级操作,保证运行的稳定性。不过它是基于APR的
(APR将在最后一节介绍),没有libmemcache的应用范围广,目前也没有很多基于它开发的程序,现有的多是一些Apache
Module,因为它不能脱离APR环境运行。但是APR倒是可以脱离Apache单独安装的,在APR网站上可以下载APR和APR-util,不需要
有Apache,可以直接安装,而且它是跨平台的。
BSM_Memcache是我在BS.Magic项目中开发的一个基于APR_Memcache的PHP扩展,说起来有点拗口,至少它把APR扯进了PHP扩展中。这个程序很简单,也没做太多的功能,只是一种形式的尝试,它支持服务器分组。
和mcache扩展支持多服务器分布存储不同,BSM_Memcache支持多组服务器,每一组内的服务器还是按照hash方式来分布保存数据,但是两个
组中保存的数据是一样的,也就是实现了热备,它不会因为一台服务器发生单点故障导致数据无法获取,除非所有的服务器组都损坏(例如机房停电)。当然实现这
个功能的代价就是性能上的牺牲,在每次添加删除数据的时候都要扫描所有的组,在get数据的时候会随机选择一组服务器开始轮询,一直到找到数据为止,正常
情况下一次就可以获取得到。
BSM_Memcache只支持这几个函数:
CODE:
zend_function_entry bsm_memcache_functions[] =
{ PHP_FE(mc_get, NULL) PHP_FE(mc_set, NULL) PHP_FE(mc_del, NULL) PHP_FE(mc_add_group, NULL) PHP_FE(mc_add_server, NULL) PHP_FE(mc_shutdown, NULL) {NULL, NULL, NULL} }; |
mc_add_group函数返回一个整形(其实应该是一个object,我偷懒了~_~)作为组ID,mc_add_server的时候要提供两个参数,一个是组ID,一个是服务器地址(ADDR
ORT)。
CODE:
/**
* Add a server group */ PHP_FUNCTION(mc_add_group) { apr_int32_t group_id; apr_status_t rv; if (0 != ZEND_NUM_ARGS()) { WRONG_PARAM_COUNT; RETURN_NULL(); } group_id = free_group_id(); if (-1 == group_id) { RETURN_FALSE; } apr_memcache_t *mc; rv = apr_memcache_create(p, MAX_G_SERVER, 0, &mc); add_group(group_id, mc); RETURN_DOUBLE(group_id); } |
CODE:
/**
* Add a server into group */ PHP_FUNCTION(mc_add_server) { apr_status_t rv; apr_int32_t group_id; double g; char *srv_str; int srv_str_l; if (2 != ZEND_NUM_ARGS()) { WRONG_PARAM_COUNT; } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ds", &g, &srv_str, &srv_str_l) == FAILURE) { RETURN_FALSE; } group_id = (apr_int32_t) g; if (-1 == is_validate_group(group_id)) { RETURN_FALSE; } char *host, *scope; apr_port_t port; rv = apr_parse_addr_port(&host, &scope, &port, srv_str, p); if (APR_SUCCESS == rv) { // Create this server object apr_memcache_server_t *st; rv = apr_memcache_server_create(p, host, port, 0, 64, 1024, 600, &st); if (APR_SUCCESS == rv) { if (NULL == mc_groups[group_id]) { RETURN_FALSE; } // Add server rv = apr_memcache_add_server(mc_groups[group_id], st); if (APR_SUCCESS == rv) { RETURN_TRUE; } } } RETURN_FALSE; } |
在set和del数据的时候,要循环所有的组:
CODE:
/**
* Store item into all groups */ PHP_FUNCTION(mc_set) { char *key, *value; int key_l, value_l; double ttl = 0; double set_ct = 0; if (2 != ZEND_NUM_ARGS()) { WRONG_PARAM_COUNT; } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|d", &key, &key_l, &value, &value_l, ttl) == FAILURE) { RETURN_FALSE; } // Write data into every object apr_int32_t i = 0; if (ttl < 0) { ttl = 0; } apr_status_t rv; for (i = 0; i < MAX_GROUP; i++) { if (0 == is_validate_group(i)) { // Write it! rv = apr_memcache_add(mc_groups[i], key, value, value_l, (apr_uint32_t) ttl, 0); if (APR_SUCCESS == rv) { set_ct++; } } } RETURN_DOUBLE(set_ct); } |
在mc_get中,首先要随机选择一个组,然后从这个组开始轮询:
CODE:
/**
* Fetch a item from a random group */ PHP_FUNCTION(mc_get) { char *key, *value = NULL; int key_l; apr_size_t value_l; if (1 != ZEND_NUM_ARGS()) { WRONG_PARAM_COUNT; } if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &key_l) == FAILURE) { RETURN_MULL(); } // I will try ... // Random read apr_int32_t curr_group_id = random_group(); apr_int32_t i = 0; apr_int32_t try = 0; apr_uint32_t flag; apr_memcache_t *oper; apr_status_t rv; for (i = 0; i < MAX_GROUP; i++) { try = i + curr_group_id; try = try % MAX_GROUP; if (0 == is_validate_group(try)) { // Get a value oper = mc_groups[try]; rv = apr_memcache_getp(mc_groups[try], p, (const char *) key, &value, &value_l, 0); if (APR_SUCCESS == rv) { RETURN_STRING(value, 1); } } } RETURN_FALSE; } |
CODE:
/**
* Random group id * For mc_get() */ apr_int32_t random_group() { struct timeval tv; struct timezone tz; int usec; gettimeofday(&tv, &tz); usec = tv.tv_usec; int curr = usec % count_group(); return (apr_int32_t) curr; } |
BSM_Memcache的使用方式和其它的client类似:
[php]
<?php
$g1 = mc_add_group(); // 添加第一个组
$g2 = mc_add_group(); // 添加第二个组
mc_add_server($g1, 'localhost:11211'); // 在第一个组中添加第一台服务器
mc_add_server($g1, 'localhost:11212'); // 在第一个组中添加第二台服务器
mc_add_server($g2, '10.0.0.16:11211'); // 在第二个组中添加第一台服务器
mc_add_server($g2, '10.0.0.17:11211'); // 在第二个组中添加第二台服务器
mc_set('key', 'Hello'); // 写入数据
$key = mc_get('key'); // 读出数据
mc_del('key'); // 删除数据
mc_shutdown(); // 关闭所有组
?>
[/php]
APR_Memcache的相关资料可以在这里找到,BSM_Memcache可以在本站下载。
◎APR环境介绍
APR的全称:Apache Portable
Runtime。它是Apache软件基金会创建并维持的一套跨平台的C语言库。它从Apache
httpd1.x中抽取出来并独立于httpd之外,Apache
httpd2.x就是建立在APR上。APR提供了很多方便的API接口可供使用,包括如内存池、字符串操作、网络、数组、hash表等实用的功能。开发
Apache2 Module要接触很多APR函数,当然APR可以独立安装独立使用,可以用来写自己的应用程序,不一定是Apache
httpd的相关开发。
发表评论
-
XMemcached使用 [转]
2012-02-05 23:11 1348Xmemcached 一、 XMemcached ... -
在CentOS 5.6上编译安装Memcached
2012-02-05 23:10 903首先上一个memcached原理图,让不了解memcached ... -
XMemcached的类图和序列图[转]
2011-04-14 22:43 938XMemcached的结构方面的文档比较少,可能对有兴趣了解它 ... -
memcache Java客户端调用小例子
2011-04-12 17:47 959上篇文章(《Linux下memcache的安装 》)介绍 ... -
Linux下memcache的安装
2011-04-12 17:47 7592010-12-01 22:24 memcac ... -
java nio的memcached客户端--xmemcached
2011-04-12 17:15 26902010-11-06 02:16 1、xmemcach ... -
Memcached更多文章
2011-04-12 15:42 940• ... -
Memcached深度分析
2011-04-12 15:41 879Memcached是danga.com ... -
memcached telnet操作
2011-04-12 15:32 1122telnet localhost 11211 //保存 ... -
命令行查看Memcached运行状态(shell或者telnet)
2011-04-12 15:31 1743stats 查看memcached状态的基本命令,通过这 ... -
Windows下Memcached安装及Java客户端调用
2011-04-12 15:28 1300Windows下的Memcache安装: 1. 下载me ...
相关推荐
3. **键值对存储**:Memcached采用键值对的存储方式,每个缓存项由一个唯一的键(key)和对应的值(value)组成,通过键来查找和操作值。 **二、Memcached的工作原理** 1. **内存存储**:Memcached所有的数据都...
64位处理器的计算能力也通常强于32位,所以运行在64位系统上的Memcached能提供更好的性能。 **安装与配置** 安装Memcached在Windows上通常涉及以下几个步骤: 1. 下载对应版本的Memcached安装包,如x86或x64。 2. ...
理论上,Memcached可以处理无限数量的连接,但实际上,由于操作系统线程能力的限制,通常建议的最大同时连接数为200。 安装libevent的过程包括下载源码包、解压、配置、编译和安装。例如,可以从指定的URL下载...
3. **配置参数**:memcached支持多种配置参数,例如最大内存(`-m`)、监听端口(`-p`)、超时时间(`-t`)等,可以根据实际需求进行调整。 4. **连接测试**:使用客户端工具如telnet或memcached客户端库,连接到...
chunk 的大小是由 `-n` 参数(默认为 48 字节)加上 item 大小(item 包括 key 和 value)计算得出,并且需要转换为 8 的倍数。 - **默认情况下**,在 64 位机器上,第一个 chunk 的大小为 96 字节。 #### 五、Slab...
6. **性能优化**:分析缓存系统对整体应用性能的影响,以及如何通过调整配置参数、优化数据访问模式等方式提升性能。 7. **监控和管理**:介绍监控和管理分布式缓存系统的方法,如日志分析、性能指标监控和故障排查...
还需要配置相关参数,如服务器地址、端口等,以便PHP能正确连接到Memcached服务。 8. **版本兼容性**:不同版本的PHP和DLL之间可能存在兼容性问题,因此在升级或更换环境时,需要确保所有组件版本匹配,以避免运行...
【酒店网站分布式计算项目概述...总的来说,"HotelWebsite-DistrComputingAssignment"项目是一个综合性的学习实践,它涵盖了Java Web开发和分布式计算的多个重要方面,对于提升学生的实际技能和理论知识具有显著价值。
在这个压缩包中,"java-perf-workshop_main.zip"包含了一个实际的性能优化工作坊项目,你可以通过运行和调试代码,亲身实践上述理论知识。"说明.txt"文件将提供详细的步骤指导和解释,帮助你逐步掌握Java Web服务...
这通常涉及流计算框架(如Apache Flink或Spark Streaming)和实时数据库(如Redis或Memcached)。 8. **AB测试** 在部署推荐系统时,AB测试是验证推荐效果的有效手段。通过对比不同推荐策略对用户行为的影响,可以...
5. **数据库参数调优**:调整数据库的配置参数,如缓冲区大小、连接池设置、事务隔离级别等,以适应不同的工作负载。 6. **并行处理**:利用多核处理器的并行计算能力,通过并行查询、并行插入等提升性能。 7. **...
- 调优:JVM参数调整,如-Xms, -Xmx, -XX:NewRatio等。 2. **多线程与并发**: - 线程状态:新建、就绪、运行、阻塞和死亡。 - 同步机制:synchronized关键字、Lock接口、ReentrantLock等。 - 死锁、活锁与饥饿...
- Session与Cookie:应用场景、存储方式及安全注意事项。 - URL重写与路由:理解mod_rewrite和.htaccess文件,以及Laravel或Symfony框架中的路由机制。 3. **PHP数据库操作**: - PDO(PHP Data Objects):安全...
例如,使用Nginx进行负载均衡,通过JVM参数调整进行性能优化,以及利用缓存技术如Redis和Memcached提升响应速度。 数据库是任何应用的基础,Java架构师需要精通多种数据库技术,包括关系型数据库MySQL、Oracle,...
13. **容器与中间件优化**:Tomcat、Jetty等Web服务器的配置优化,缓存系统(如Redis、Memcached)的使用,以及消息队列(如RabbitMQ、Kafka)在解耦和性能提升中的应用。 14. **监控与报警**:建立全面的系统监控...
4. **预编译与参数化查询**:预编译的SQL语句可以减少解析时间,参数化查询则能防止SQL注入。 三、SQL语句优化高级策略 1. **物化视图与汇总表**:对于常见的聚合查询,可以创建物化视图或汇总表,预先计算好结果...
2. **垃圾回收与内存管理**:了解Java的自动内存管理机制,包括对象生命周期、垃圾回收算法(如分代收集、G1、ZGC等)以及如何调整内存参数以避免内存泄漏和Full GC。 3. **并发编程**:Java提供了丰富的并发库,如...
避免冗余计算,合理使用数据结构与算法,减少不必要的对象创建(如避免频繁的new操作),以及使用StringBuilder而非+操作符进行字符串拼接等。此外,理解并运用设计模式,如单例模式、工厂模式等,可以提高代码的...
数据模型是描述数据结构、操作和约束的一种方式,常见的数据模型有层次模型、网状模型、关系模型以及近年来流行的NoSQL模型。关系模型是最常用的数据模型,基于E-R(实体-关系)理论,通过实体、属性和关系来描述...