当前访问本站: hits

yjhmily

坚持走自己的路……

  BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  100 Posts :: 8 Stories :: 353 Comments :: 0 Trackbacks

2011年8月22日 #

原文出处:http://space.itpub.net/133735/viewspace-710117 
总结的不错!
-------------------------------------------------------------------------------------------------
生产环境最佳实践
1.linux 系统:
1】关闭文件系统/分区的atime 选项
Vi /etc/fstab
在对应的分区项后面添加noatime ,nodiratime
LABEL=/1 / ext3 defaults 1 1
LABEL=/data1 /data ext4 defaults,noatime,nodiratime 1 2
2】设置文件句柄4k+,目前该配置已经集成到启动脚本中。
Vi /etc/security/limit.conf
* soft nproc 65536
* hard nproc 65536
* soft nofile 65536
* hard nofile 65536
3】不要使用large vm page (不要使用大内存页选项)
Linux 大内存页参考:http://linuxgazette.net/155/krishnakumar.html
4】用dmesg 查看主机的信息。
2.linux 文件系统的选择:
Mongodb 采用预分配的大文件来存储数据,我们推荐
1】ext4
2】xfs
3.内核版本:
网络上对2.6.33-31 以及2.6.32 的表现持怀疑度, 而强力推荐2.6.36
4.线程堆栈的尺寸
默认的线程堆栈尺寸为10m ,调整为1m ,已经集成在启动脚本中。
项目过程中的总结与建议
1.大小写问题
mongodb 是默认区分大小写的,但是这会不会衍生出跟mysql 一样的问题?(mysql 区
分大小写,导致windows 与linux 下的表名,字段名不一致)。
如果无特别用途,建议表名,字段名全部用小写字母。
2.尽可能的缩短字段名的长度
mongodb 的schema free 导致了每笔数据都要存储他的key 以及属性,这导致了这些数
据的大量冗余。开发同事也许考虑到,从易读性出发设计的key 基本比较长,基本都是按
照起字面意思去设计的。这导致key 很长。对应的数据存储占用了很大的空间。
必要的时候,可以考虑建立一个key 与实际意义的map 表,尽量降低key 的长度。
示例定义:
// 基本信息
static final String _ID = "_id";
static final String STATUS_CODE = "sc";
// 缓冲
static final String DATE = "date";
static final String MAX_AGE = "age";
// 内容
static final String CONTENT = "content";
static final String CONTENT_TYPE = "ctype";
static final String CONTENT_LENGTH = "clen";
static final String ZIP = "zip";
3. mongodb 单表最大索引数为64
无索引排序的最大数据量为4M, 超过则报错退出。
建议where 条件尽量落在索引字段上,排序字段需要建立索引,索引的使用原则与oracle
mysql 一致,尽量降低索引数量,索引长度。
mongodb 的查询每次只能用到一个索引,对数据的查询不会“并发”执行
例如: db.tab.find({'id'=1,'name'=2}) 如果‘id’,‘name' 列上分别有索引
对查询效率提升意义不大,如果索引为('id','name') 则大幅提升效率。
4.mongodb 添加字段
如果添加字段且带有default 值,需要全部数据都要修改,这也是设计阶段需要考虑的
事情,这个问题的另外一种解法是应用代码里做一次判断。
5.测试过程的密码问题
对于用作数据库使用的Mongodb,在代码测试阶段都应加上密码验证,目前上线阶段基
本都会在密码验证方面出现问题(做缓存使用的可以不做密码验证)。
6.数据源连接方式
使用连接池模式,尽量减少认证带来的性能额外消耗
建议采用标准的uri 连接方式: mongodb://user:passwd@host:port,host:port/db
7.Mongodb日志量
正常情况下不需要开启-v 日志选项。
Mongodb 的-v 日志适合在开发环境的调试线上部署不建议采用这个参数,目前线上
部署的情况,-v 日志一天也会有几个G 的日志量,去掉这个参数,跟数据查询相关的操作
就不会记日志了,数据库的内部的重要操作还是会写日志的。
8.连接数大小的设置
Mongodb 驱动程序采用的连接池的方式连接到数据库,目前从观察到的情况是应用一
开启便根据变量的设置,建立全部连接,然后提供给程序使用,并且一旦其中某个连接
到数据库的访问失败,则会清空整个连接池到这台数据库的连接,并重新建立连接。
而mongodb 对中断连接的垃圾清理工作则是懒惰的被动清理方式,如果驱动程序端配
置的连接数过大,一旦发生重连,则会导致mongo 端堆积大量的垃圾连接数据,导致
主机资源耗尽。
建议: mongodb 驱动的连接池大小的设置一般应该控制100 以下,一般情况30-50 足
够支撑应用访问。
9.锁的问题
Mongodb 对数据库的访问全部加锁,如果是查询请求则设置共享锁,数据修改请求,
则设置全局排他锁,并且是实例级别的排他锁。并且写锁会阻塞读请求,如果长时间持有
写锁,会阻塞整个实例的读请求。
部署建议:
1】一般情况下,建议不同的应用不要合用一套示例。
2】如果资源不满足,需要合用,应该具有相同属性的应用合用一套实例。
例如合同mongo 的应用都是读多写少,防止一台写多应用阻塞读请求。
10.关于map/reduce问题
mongodb 对map/reduce 的支持是单线程的,我们不建议在前台使用该功能, group by
是通过map/reduce 实现的,开发过程中,要慎用。
11.安全问题
1】Mongodb 运行在mongodb 用户之上,并禁止mongodb 用户登录
2】使用Mongodb 自带的认证方法(adduser、auth)限制用户访问行为
3】将Mongodb 置于内网环境中
4】Mongodb 必须暴露在外网环境中的时候,使用IPTABLES 等网络层技术进行防护
5】网络层面内容为明文传输,可以考虑存储加密文档,应用端,加解密。
12.性能监控
Mongodb 自带有性能数据收集系统
Mongostat 实时采集数据库的多项指标,提供http console 端口号为应用端口号+1000。
关注的主要性能指标:
1】Faults:显示Mongodb 每秒页面故障的数量,这个是mongoDB 映射到虚拟地址空间,
而不是物理内存,这个值如果飙高的话,可能意味着机器没有足够的内存来
存储数据和索引。
2】Flushes:每秒做了多少次fsync,显示多少次数据被刷新进了磁盘
3】locked:写锁
4】idx miss:索引未命中比例
5】qr | qw:读写锁的请求队列长度。
6】conn: 当前已经建立的连接数。
其他命令:
Db.stat()
db.serverStatuse()
Db.collection.stats()
13.碎片问题
Mongodb 数据库如果数据修改很频繁,会出现比较严重的空间碎片问题,表现在磁盘
文件扩张与实际数据量不相符,内存不够用,索引命中率低,查询效率降低。
碎片整理,目前我们采用的版本没有太有效的方法。
可以用db.repaireDatabase() 来整理数据库,这个过程非常的慢
如果是Master-slave 模式则相当于执行一次主从切换,然后从新建立从库。
如果是replSet 架构可以停掉数据库,然后删除数据目录,从新从复制复制组中全同步数据,
这个时候要考虑oplog 的尺寸。
一个大体的步骤:
1.】先调用rs.freeze(1200),将每个不想让它成为primary 的机器让它在1200 秒内无法成为
primary(这步也可以不做)
2. 】将primary stepDown,不出意外新的primary 会起来.
3. 】将原primary kill 掉.
4. 】删掉所有data 数据(调用repair 很慢,真不如干掉重新来)
5. 】再重启动原primary 的进程
6. 】以此循环完成整个复制组的全部重建。
14.系统备份:
Mongodb 目前不支持在线备份,只能离线备份。
我们采用的架构为replSet 和Master-slave .
基于我们目前的架构以及数据一致性要求,我们没有安排相关的备份系统。
15.应用代码中Mongodb连接问题
在有些应用在使用Mongodb 过程中会存在以下两个小问题:
1. 在应用启动过程中,应用存在要求连接池中所有的连接都建立成功才让应用正
常启动,这种做法不可取,因为存在网络问题、Mongodb 拒绝连接或Mongodb 假死情况,如
果没加外部try catch 做防护,则Resin 不断重启也不能正常启动端口。
2.有些应用在使用Mongodb 中连接池配置了safe=true,w=1;这种配置意味着客户端在
插入数据或更新数据的时候,要求mongodb 必须将所更新的数据写入磁盘并返回更新成功
的信息给程序。如果碰上应用程序访问压力大,mongodb 就会反应迟钝,并会发生假死可能,
针对此情况,需要评估数据的一致性需求,做出合适调整。我们一般建议关闭此选项。
16.补充开发方面的一些问题
1】skip+limit翻页,越往后面越慢,有资料说用数组元素的分页可以解决,目前还没
试过,比较靠谱的做法是,先找出上次的id,翻页的时候不用skip:
last_row_id = ObjectId(‘....’);
db.activity_stream->find({_id:{$lt: last_row_id },
user_id:20 } ).sort( {_id:-1} ).limit(10);
2】.只有真正需要的字段才select出来
3】.更新的某条数据的时候,先查出来再更新会减小锁的时间
4】.只有返回很少结果的查询才用索引,否则会加载太多数据,比没有用索引还慢
5】.属性比较多的时候,建立分层的关系能够提高查询效率,否则每个记录都要过一遍
才能找到要的属性
17.关于硬件资源的选择:
虚拟机可以很好的隔离资源,并可动态的扩展。
我们建议mongodb 的部署采用虚拟机的方式,每个虚拟机部署一个实例,使各节点分
散在不同的物理机上,根据应用的前期预测,平衡虚拟机的之间的i/o。
posted @ 2012-09-29 22:17 kangxm 阅读(617) | 评论 (0)编辑 收藏

adb shell

# mount -oremount,rw /dev/block/mtdblock3 /system

# pm list packages -f (列出apk和包名的对应关系)
# cd /system/app (APK文件所在地)
# rm Mms.* (rom自带的短信)
# exit

 

adb uninstall com.android.mms

 

返回Success,就说明卸载成功了

 

注意..
删除之前, 最好用

  1. adb pull /system/app/xxx.apk .

复制代码

给备份一下, 避免出错(系统老是Force Close, 没法用).
出错后, 可以用

  1. adb push xxx.apk /system/app
adb shell

# mount -oremount,rw /dev/block/mtdblock3 /system

# pm list packages -f (列出apk和包名的对应关系)
# cd /system/app (APK文件所在地)
# rm Mms.* (rom自带的短信)
# exit

 

adb uninstall com.android.mms

 

返回Success,就说明卸载成功了

 

注意..
删除之前, 最好用

  1. adb pull /system/app/xxx.apk .

复制代码

给备份一下, 避免出错(系统老是Force Close, 没法用).
出错后, 可以用

  1. adb push xxx.apk /system/app
posted @ 2012-08-10 17:56 kangxm 阅读(514) | 评论 (0)编辑 收藏

最近的机器内存又爆满了,出了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了。
下面是参考网络资源和总结一些在java编程中尽可能做到的一些地方
-
1.尽量在合适的场合使用单例
使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面
第一,控制资源的使用,通过线程同步来控制资源的并发访问
第二,控制实例的产生,以达到节约资源的目的
第三,控制数据共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信
-
2.尽量避免随意使用静态变量
要知道,当某个对象被定义为stataic变量所引用,那么gc通常是不会回收这个对象所占有的内存,如
public class A{
static B b = new B();
}
此时静态变量b的生命周期与A类同步,如果A类不会卸载,那么b对象会常驻内存,直到程序终止。
-
3.尽量避免过多过常的创建java对象
尽量避免在经常调用的方法,循环中new对象,由于系统不仅要花费时间来创建对象,而且还要花时间对这些对象进行垃圾回收和处理,在我们可以控制的范围内,最
大限度的重用对象,最好能用基本的数据类型或数组来替代对象。
-
4.尽量使用final修饰符
带 有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String。为String类指 定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联 (inline)所有的final方法(这和具体的编译器实现有关)。此举能够使性能平均提高50%。
-
5.尽量使用局部变量
调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量,实例变量等,都在堆(Heap)中创建,速度较慢。
-
6.尽量处理好包装类型和基本类型两者的使用场所
虽然包装类型和基本类型在使用过程中是可以相互转换,但它们两者所产生的内存区域是完全不同的,基本类型数据产生和处理都在栈中处理,包装类型是对象,是在堆中产生实例。
在集合类对象,有对象方面需要的处理适用包装类型,其他的处理提倡使用基本类型。
-
7.慎用synchronized,尽量减小synchronize的方法
都 知道,实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。synchronize方法被调用时,直接会把当前对象锁 了,在方法执行完之前其他线程无法调用当前对象的其他方法。所以synchronize的方法尽量小,并且应尽量使用方法同步代替代码块同步。
-
8.尽量使用StringBuilder和StringBuffer进行字符串连接
这个就不多讲了
-
9.尽量不要使用finalize方法
实际上,将资源清理放在finalize方法中完成是非常不好的选择,由于GC的工作量很大,尤其是回收Young代内存时,大都会引起应用程序暂停,所以再选择使用finalize方法进行资源清理,会导致GC负担更大,程序运行效率更差。
-
10.尽量使用基本数据类型代替对象
String str = "hello";
上面这种方式会创建一个“hello”字符串,而且JVM的字符缓存池还会缓存这个字符串;
String str = new String("hello");
此时程序除创建字符串外,str所引用的String对象底层还包含一个char[]数组,这个char[]数组依次存放了h,e,l,l,o
-
11.单线程应尽量使用HashMap, ArrayList
HashTable,Vector等使用了同步机制,降低了性能。
-
12.尽量合理的创建HashMap
当你要创建一个比较大的hashMap时,充分利用另一个构造函数
public HashMap(int initialCapacity, float loadFactor)
避 免HashMap多次进行了hash重构,扩容是一件很耗费性能的事,在默认中initialCapacity只有16,而loadFactor是 0.75,需要多大的容量,你最好能准确的估计你所需要的最佳大小,同样的Hashtable,Vectors也是一样的道理。
-
13.尽量减少对变量的重复计算
for(int i=0;i<list.size();i++)
应该改为
for(int i=0,len=list.size();i<len;i++)
并且在循环中应该避免使用复杂的表达式,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。 
-
14.尽量避免不必要的创建
A a = new A();
if(i==1){list.add(a);}
应该改为
if(i==1){
A a = new A();
list.add(a);}
-
15.尽量在finally块中释放资源
程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。 
-
16.尽量使用移位来代替'a/b'的操作
"/"是一个代价很高的操作,使用移位的操作将会更快和更有效
int num = a / 4;
int num = a / 8;
应该改为
int num = a >> 2;
int num = a >> 3;
但注意的是使用移位应添加注释,因为移位操作不直观,比较难理解
-
17.尽量使用移位来代替'a*b'的操作
同样的,对于'*'操作,使用移位的操作将会更快和更有效
int num = a * 4;
int num = a * 8;
应该改为
int num = a << 2;
int num = a << 3;
-
18.尽量确定StringBuffer的容量
StringBuffer 的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再 丢弃旧的数组。在大多数情况下,你可以在创建 StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。 
如:StringBuffer buffer = new StringBuffer(1000);  
-
19.尽量早释放无用对象的引用
大部分时,方法局部引用变量所引用的对象 会随着方法结束而变成垃圾,因此,大部分时候程序无需将局部,引用变量显式设为null。
例如:
Public void test(){
Object obj = new Object();
……
Obj=null;
}
上面这个就没必要了,随着方法test()的执行完成,程序中obj引用变量的作用域就结束了。但是如果是改成下面:
Public void test(){
Object obj = new Object();
……
Obj=null;
//执行耗时,耗内存操作;或调用耗时,耗内存的方法
……
}
这时候就有必要将obj赋值为null,可以尽早的释放对Object对象的引用。
-
20.尽量避免使用二维数组
二维数据占用的内存空间比一维数组多得多,大概10倍以上。
-
21.尽量避免使用split
除 非是必须的,否则应该避免使用split,split由于支持正则表达式,所以效率比较低,如果是频繁的几十,几百万的调用将会耗费大量资源,如果确实需 要频繁的调用split,可以考虑使用apache的StringUtils.split(string,char),频繁split的可以缓存结果。
-
22.ArrayList & LinkedList
一 个是线性表,一个是链表,一句话,随机查询尽量使用ArrayList,ArrayList优于LinkedList,LinkedList还要移动指 针,添加删除的操作LinkedList优于ArrayList,ArrayList还要移动数据,不过这是理论性分析,事实未必如此,重要的是理解好2 者得数据结构,对症下药。
-
23.尽量使用System.arraycopy ()代替通过来循环复制数组
System.arraycopy() 要比通过循环来复制数组快的多 
-
24.尽量缓存经常使用的对象
尽可能将经常使用的对象进行缓存,可以使用数组,或HashMap的容器来进行缓存,但这种方式可能导致系统占用过多的缓存,性能下降,推荐可以使用一些第三方的开源工具,如EhCache,Oscache进行缓存,他们基本都实现了FIFO/FLU等缓存算法。
-
25.尽量避免非常大的内存分配
有时候问题不是由当时的堆状态造成的,而是因为分配失败造成的。分配的内存块都必须是连续的,而随着堆越来越满,找到较大的连续块越来越困难。
-
26.慎用异常
当 创建一个异常时,需要收集一个栈跟踪(stack track),这个栈跟踪用于描述异常是在何处创建的。构建这些栈跟踪时需要为运行时栈做一份快照,正是这一部分开销很大。当需要创建一个 Exception 时,JVM 不得不说:先别动,我想就您现在的样子存一份快照,所以暂时停止入栈和出栈操作。栈跟踪不只包含运行时栈中的一两个元素,而是包含这个栈中的每一个元素。
如 果您创建一个 Exception ,就得付出代价。好在捕获异常开销不大,因此可以使用 try-catch 将核心内容包起来。从技术上讲,您甚至可以随意地抛出异常,而不用花费很大的代价。招致性能损失的并不是 throw 操作——尽管在没有预先创建异常的情况下就抛出异常是有点不寻常。真正要花代价的是创建异常。幸运的是,好的编程习惯已教会我们,不应该不管三七二十一就 抛出异常。异常是为异常的情况而设计的,使用时也应该牢记这一原则。

文章主要是为了抛砖引玉,希望有更多牛人的指点

谢谢的 xuanyuan 的建议:
===================================================
7.慎用synchronized,尽量减小synchronize的方法
re:同意,不过文中有个地方说错了,使用synchronized关键字并不一定都是锁定当前对象的,要看具体的锁是什么。如果是在方法上加的synchronized,则是以对象本身为锁的,如果是静态方法则锁的粒度是类。
---------------
9.尽量不要使用finalize方法
re:同意,其实不推荐用finalize方法的根本原因在于,JVM的规范并不保证何时执行该方法,所以用这个方法来释放资源很不合适,有可能造成长时间资源得不到释放。
---------------
16.尽量使用移位来代替'a/b'的操作;17.尽量使用移位来代替'a*b'的操作
re:个人不太同意这两条。这样做确实有更好的性能,但是却牺牲了可读性。这两个操作符对很多程序员来说并不直观。我认为在如今硬件价格不那么昂贵的情况下,略微牺牲一些性能,换来更好的可读性和可维护性是好的选择。
===================================================
19.尽量早释放无用对象的引用
大部分时,方法局部引用变量所引用的对象 会随着方法结束而变成垃圾,因此,大部分时候程序无需将局部,引用变量显式设为null。
例如:
Public void test(){
Object obj = new Object();
……
Obj=null;
}
上面这个就没必要了,随着方法test()的执行完成,程序中obj引用变量的作用域就结束了。但是如果是改成下面:
Public void test(){
Object obj = new Object();
……
Obj=null;
//执行耗时,耗内存操作;或调用耗时,耗内存的方法
……
}
如果Object obj = new Object(); 如果这对象并不是大对象,这有必要吗?Obj=null;只是告诉jvm这个对象已经成为垃圾,至于什么时候回收,还不能确定! 这可读性也不好!
===================================================
posted @ 2011-08-22 15:18 kangxm 阅读(542) | 评论 (0)编辑 收藏