ホームページ >データベース >mysql チュートリアル >笔记-beam-20140503_MySQL
处理erlang beam占用大量内存方法
第一步:
查看进程数目是否正常? erlang:system_info(process_count). 进程数目合理
第二步:
查看节点的内存消耗在什么地方?
> erlang:memory().
显示内存大部分消耗在进程上,由此确定是进程占用了大量内存
第三步:
查看哪些进程占用内存最高?
> spawn(fun() -> etop:start([{output, text}, {interval, 1}, {lines, 20}, {sort, memory}]) end).
(以输出text方式启动etop,其间隔为1秒,输出行数为20行,按照内存排序. 这里spawn一个新进程,目的是输出etop数据时不影响erlang shell 输入.)
top输出有点乱,超过一定范围变成了**,不过我们已经找到了内存占用最高的进程.
第四步:
查看占用内存最高的进程状态
> erlang:process_info(pid(0,12571,0)).
第五步:
手动gc回收,希望问题可以解决
> erlang:garbage_collect(pid(0,12571,0)).
true
再次查看进程内存,发现没有任何变化!gc没有回收到任何资源,因此消耗的内存还在发挥作用,没有回收!
尾递归! try…catch会在stack中保存相应的信息,异常捕获需要放置在函数内部,所以send_msg最后调用的是try…catch,而不是自身,所以不是尾递归!
总结:
1,服务器编程中,循环一定确保为尾递归
2,善于使用OTP,如果使用gen_server替换手写loop,就不会出现这个问题!
1.back_log
当你观察你的主机进程列表,发现大量 264084 | unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL 的待连接进程时,就要加大 back_log 的值了。默认数值是50,我把它改为500。
2.interactive_timeout:
服务器在关闭它前在一个交互连接上等待行动的秒数。一个交互的客户被定义为对 mysql_real_connect()使用 CLIENT_INTERACTIVE 选项的客户。 默认数值是28800,我把它改为7200。
3.key_buffer_size:
索引块是缓冲的并且被所有的线程共享。key_buffer_size是用于索引块的缓冲区大小,增加它可得到更好处理的索引(对所有读和多重写),到你能负担得起那样多。如果你使它太大,系统将开始换页并且真的变慢了。默认数值是8388600(8M),我的MySQL主机有2GB内存,所以我把它改为402649088(400MB)。
(4)、max_connections:
允许的同时客户的数量。增加该值增加 mysqld 要求的文件描述符的数量。这个数字应该增加,否则,你将经常看到 Too many connections 错误。 默认数值是100,我把它改为1024 。
(5)、record_buffer:
每个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区。如果你做很多顺序扫描,你可能想要增加该值。默认数值是131072(128K),我把它改为16773120 (16M)
(6)、sort_buffer:
每个需要进行排序的线程分配该大小的一个缓冲区。增加这值加速ORDER BY或GROUP BY操作。默认数值是2097144(2M),我把它改为 16777208 (16M)。
(7)、table_cache:
为所有线程打开表的数量。增加该值能增加mysqld要求的文件描述符的数量。MySQL对每个唯一打开的表需要2个文件描述符。默认数值是64,我把它改为512。
(8)、thread_cache_size:
可以复用的保存在中的线程的数量。如果有,新的线程从缓存中取得,当断开连接的时候如果有空间,客户的线置在缓存中。如果有很多新的线程,为了提高性能可以这个变量值。通过比较 Connections 和 Threads_created 状态的变量,可以看到这个变量的作用。我把它设置为 80。
(10)、wait_timeout:
服务器在关闭它之前在一个连接上等待行动的秒数。 默认数值是28800,我把它改为7200。
注:参数的调整可以通过修改 /etc/my.cnf 文件并重启 MySQL 实现。
设计队列表时会遇到哪些挑战:
1)表的读写。
由于入队列和出队列是相互影响的,在高负载下可能会导致锁竞争、事务死锁、IO超时等等。
2)当多个接收者试图从同一队列读数据时,它们会随机地获取重复项,因而导致重复的处理过程。
你需要在队列上实现一些高性能的行锁定,以便让并发接受器不会接收相同的数据项。
3)队列表需要以某种顺序存储行以及以某种顺序读取行,这使得设计索引很棘手。
队列表并不总是遵守先进先出的,有时候顺序中的消息带有更高的优先级,无论这个消息是否入队列都要先处理它。
4)队列表需要以XML或二进制的形式序列化对象,这使得存储和重建索引很麻烦。
你不能在队列表中重建索引,因为它包含了文本或二进制字段。因此,每过一天,数据表会变得越来越慢,最后查询会超时,你不得不关闭服务并重建索引。
5)出队列的过程中,一批行数据被选中、被更新,然后返回数据。你需要一个”State”(状态)列来定义数据项的状态。出队列时,你只需选择某个状态的数据项。现在状态只有几种类型:PENDING(待定)、PROCESSING(处理中)、PROCESSED(已处理)、ARCHIVED(存档)。你不能在状态列上创建索引,因为不能提供足够的选择性,具有相同的状态的数据行有成千上万。因此,任何出队列操作都会导致集群的索引被重新扫描,这属于CPU和IO密集型操作,会产生锁竞争。
6)在出队列的过程中,你不能仅仅移除队列表的相关行,因为这很容易导致数据表产生存储碎片。而且,你还需要重新处理订单/任务/通知做N次操作以防止这些操作在第一次中失败。这意味着存储行数据需要更长的时间、索引会持续增长以及出队列越来越慢。
7)你必须归从入队表把处理过的数据项归档到不同的数据表或数据库,以保持主队列表的精简。这意味着需要移动大量的带有特定状态的数据行到另一个数据库。如此大的数据移动会频繁产生存储碎片,以至于降低入队列和出队列的性能。
8)你有24×7不间断的业务。你不能停止服务再归档大量的行数据。这意味者你必须在不影响入栈和出栈通信的情况下持续的归档行数据
OpenAMQ
情况好时短超时+重试机制效果也不错,而且系统更measurable
https://github.com/tiancaiamao/go-internals/blob/master/ebook/preface.md
http://blog.chinaunix.net/uid-301743-id-4144744.html