基于Redis的开源分布式服务Codis

Redis在豌豆荚的用过程——单实例==》多实例,业务代码中开sharding==》单个Twemproxy==》多独Twemproxy==》Codis,豌豆荚自己开支之分布式Redis服务。在大的Redis使用过程遭到,他们发现Redis受限于多独面:单机内存有数、带富压力、单点问题、不可知动态扩容以及磁盘损坏时之数抢救。

如出一辙、编程规约

澳门美高梅手机网站 1

(一) 命名规约

  1. 【强制】
    代码中之命名均无克以下划线或美元符号开始,也无可知以下划线或美元符号结束。

  反例: _nam / __name / $Object / name_  / name$ / Object$

  1. 【强制】
    代码中之命名严禁用拼音与英文混合的主意,更非允直接行使中文的法门。

  说明:正确的英文拼写及语法可以让阅读者易于掌握,避免歧义。注意,即使纯拼音命名方式呢要是避下。

  反例: DaZhePromotion [打折] / getPingfenByName() [评分] / int
某变量 = 3

  正例: alibaba / taobao / youku / hangzhou
等国际通用的称号,可观看同英文。
3.
【强制】类名使用UpperCamelCase风格,必须信守驼峰形式,但以下状况不同:(领域模型的连带命名)DO
/ BO / DTO / VO等。

  正例:MarcoPolo / UserDO / XmlService / TcpUdpDeal / TaPromotion

  反例:macroPolo / UserDo / XMLService / TCPUDPDeal / TAPromotion
4.
【强制】方法名、参数名叫、成员变量、局部变量都统一采用lowerCamelCase风格,必须遵从驼峰形式。

  正例: localValue / getHttpMessage() / inputUserId
5.
【强制】常量命名全部大写,单词里用生划线隔开,力求语义表达完清楚,不要嫌名字长。

  正例: MAX_STOCK_COUNT

  反例: MAX_COUNT
6.
【强制】抽象类命名使用Abstract或Base开头;异常类命名使用Exception结尾;测试类命名为它们如果测试的切近的称开始,以Test结尾。

  1. 【强制】中括号是数组类型的同一有,数组定义如下:String[] args;

  反例:请不以String args[]的法来定义。
8.
【强制】POJO类中布尔种的变量,都无须加is,否则有框架解析会挑起序列化错误。

  反例:定义为基本数据类boolean
isSuccess;的习性,它的办法吧是isSuccess(),RPC框架在倒朝解析的早晚,“以为”对应的性能名称是success,导致性获取不交,进而抛出异常。
9.
【强制】包名统一运用小写,点分隔符之间来且只来一个自然语义的英语单词。包名统一用单数形式,但是类名如果发生复数含义,类名可以应用复数形式。

   正例:
应用工具类包名为com.alibaba.open.util、类名为MessageUtils(此规则参考spring的框架结构)

  1. 【强制】杜绝了无专业之缩写,避免望文不知义。

  反例: AbstractClass“缩写”命名成AbsClass;condition“缩写”命名成
condi,此类随意缩写严重下滑了代码的不过阅读性。

  1. 【推荐】如果下及了设计模式,建议以类名中体现出切实可行模式。

  说明:将设计模式体现于名字中,有利于阅读者快速解架构设计思想。

  正例:public class OrderFactory;

     public class LoginProxy;

     public class ResourceObserver;

  1. 【推荐】接口类中的主意及性不苟加任何修饰符号(public
    也不用加),保持代码的简洁性,并加上有效之Javadoc注释。尽量不要以接口里定义变量,如果一定要定义变量,肯定是和接口方法有关,并且是整整应用之基本功常量。

  正例:接口方法签名:void f(); 接口基础常量表示:String COMPANY =
“alibaba”;

  反例:接口方法定义:public abstract void f();
说明:JDK8中接口允许发生默认实现,那么这default方法,是对准具备实现类似都有价之默认实现。

  1. 接口和贯彻类似的命名有些许仿照规则:

  1)【强制】对于Service和DAO类,基于SOA的见,暴露出来的劳动得是接口,内部的贯彻类似用Impl的后缀与接口区别。

  正例:CacheServiceImpl实现CacheService接口。

   2) 【推荐】
如果是描摹能力的接口名称,取对应之形容词做接口名(通常是–able的样式)。

  正例:AbstractTranslator实现 Translatable。
14.
【参考】枚举类名建议带达Enum后缀,枚举成员称需要全大写,单词里用生划线隔开。

  说明:枚举其实就算是例外的常量类,且构造方法被默认强制是患得患失出。

  正例:枚举名字:DealStatusEnum,成员称:SUCCESS /
UNKOWN_REASON。

  1. 【参考】各层命名规则:

   A) Service/DAO层方法命名规则

    1) 获取单个对象的法门用get做前缀。

    2) 获取多只对象的方用list做前缀。

    3) 获取统计值的道用count做前缀。

    4) 插入的计用save(推荐)或insert做前缀。

    5) 删除的不二法门用remove(推荐)或delete做前缀。

    6) 修改的方法用update做前缀。

  B) 领域模型命名规则

    1) 数据对象:xxxDO,xxx即为数表名。

    2) 数据传对象:xxxDTO,xxx为业务领域相关的称。

    3) 展示对象:xxxVO,xxx一般为网页名称。

    4) POJO是DO/DTO/BO/VO的统称,禁止命名成xxxPOJO。

Redis通常有3个下途径:客户端静态分片,一致性哈希;通过Proxy分片,即Twemproxy;还有就是是官的Redis
Cluster,但时至今日无一个初本子。随后刘奇还详实的分析了怎么不下Twemproxy和Redis
Cluster:

(二) 常量定义

  1. 【强制】不允出现其他魔法值(即未经定义的常量)直接出现于代码中。

  反例: String key=”Id#taobao_”+tradeId;

     cache.put(key, value);
2.
【强制】long或者Long初始赋值时,必须使大写的L,不能够是小写的l,小写好和数字1歪曲,造成误解。

  说明:Long a = 2l; 写的是数字的21,还是Long型的2?
3.
【推荐】不要使一个常量类保护有常量,应该按照常量功能拓展分拣,分开维护。如:缓存相关的常量放在类:CacheConsts下;系统部署相关的常量放在类:ConfigConsts下。

  说明:大如俱的常量类,非得用查找功能才能够定点及修改的常量,不便于理解与保障。
4.
【推荐】常量的复用层次来五交汇:跨应用共享常量、应用内共享常量、子工程外共享常量、包内共享常量、类内共享常量。

  1)
跨应用共享常量:放置于二方库中,通常是client.jar中的constant目录下。

  2) 应用内共享常量:放置于一方库的modules中的constant目录下。

    反例:易亮变量也使合并定义成应用内共享常量,两各类攻城师在有限独像样中分别定义
了代表“是”的变量:

       类A中:public static final String YES = “yes”;

       类B中:public static final String YES = “y”;
A.YES.equals(B.YES),预期是true,但实际返回吗false,导致发生线上问题。
  3) 子工程中共享常量:即当当前子工程的constant目录下。

  4) 包内共享常量:即于时下包下单独的constant目录下。

  5) 类内共享常量:直接以接近中private static final定义。
5.
【推荐】如果变量值仅以一个限制外变化用Enum类。如果还包含名称之外的延伸属性,必须采用Enum类,下面正例中之数字就是是延长信息,表示星期几。

  正例:public Enum{ MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4),
FRIDAY(5), SATURDAY(6), SUNDAY(7);}

Twemproxy:最特别之痛点是无能为力平滑的扩容或者缩容,甚至修改配置都亟待更开服务;其次,不可运维,甚至无Dashboard。

(三) 格式规约

1.
【强制】大括如泣如诉的使用约定。如果是大括哀号内为空,则简洁地写成{}即可,不待换行;如果是非空代码块则:

  1) 左大括号前方不换行。

  2) 左大括号后换行。

  3) 右大括号前换行。

  4) 右大括号后还有else等代码则未换行;表示已右大括声泪俱下后必换行。

  1. 【强制】
    左括号与晚一个字符中无出新空格;同样,右括号及前边一个字符中为未起空格。详见第5漫漫凡正例提示。
  2. 【强制】if/for/while/switch/do等保留字与左右括号内还必加空格。
  3. 【强制】任何运算符左右必须加以一个空格。

  说明:运算符包括赋值运算符=、逻辑运算符&&、加减乘除符号、三瞧运行符等。

  1. 【强制】缩进采用4单空格,禁止以tab字符。
    说明: 如果用 tab 缩进,必须安装 缩进,必须设置 缩进,必须装
    缩进,必须装 缩进,必须装 缩进,必须安装 1单 tab 为 4只空格。 IDEA
    设置 tab 为 4个空格时, 请勿勾选 Use tab character ;而在 eclipse
    中,必须勾选 insert spaces for tabs 。
    正例: (涉及1-5点)

    public static void main(String args[]) {

         // 缩进4个空格
         String say = "hello";
         // 运算符的左右必须有一个空格
         int flag = 0;
         // 关键词if与括号之间必须有一个空格,括号内的f与左括号,0与右括号不需要空格
         if (flag == 0) {
             System.out.println(say);
         }
         // 左大括号前加空格且不换行;左大括号后换行
         if (flag == 1) {
             System.out.println("world");
             // 右大括号前换行,右大括号后有else,不用换行
         } else {
             System.out.println("ok");
             // 在右大括号后直接结束,则必须换行
         }
     }
    
  2. 【强制】单行字符数限不超 120 个,超出需要换行时 个,超出需要换行时
    遵循如下原则:

  1) 第二履相对一缩进 4个空格,从第三尽开始不再继续缩进参考示例。

  2) 运算符与下文一起换行。

  3) 方法调用的点符号与下文一起换行。

  4) 在差不多只参数超长,逗号后进行换行。

  5) 在括号前不要换行,见反例。

  正例:
    StringBuffer sb = new StringBuffer();
    //超过120只字符的状况下,换行缩进4独空格,并且方法前之点符号一起换行
    sb.append(“zi”).append(“xin”)…
    .append(“huang”)…
    .append(“huang”)…
    .append(“huang”);
  反例:
    StringBuffer sb = new StringBuffer();
    //超过120单字符的场面下,不要当括号前换行
    sb.append(“zi”).append(“xin”)…append
    (“huang”);
    //参数很多底点子调用可能逾120个字符,不要当逗号前换行
    method(args1, args2, args3, …
    , argsX);

  1. 【强制】方法参数在概念和散播时,多独参数逗号后边必须加空格。

  正例:下例中实参的”a”,后止必须使来一个空格。
    method(“a”, “b”, “c”);

  1. 【强制】IDE的text file encoding设置也UTF-8;
    IDE中文件的换行符使用Unix格式,不要采取windows格式。
  2. 【推荐】没有必要增加多空格来要有平履的字符与上一行的附和字符对合。

  正例:

int a = 3;
long b = 4L;
float c = 5F;
StringBuffer sb = new StringBuffer();

征:增加sb这个变量,如果需要针对同步,则叫a、b、c都要增加几独空格,在变量比较多之情况下,是平栽累赘的事务。
10.
【推荐】方法体内的实践语句组、变量的概念语句组、不同之工作逻辑中或者不同的语义之间插入一个空行。相同业务逻辑和语义之间未待插入空行。

  说明:没有必要插入多执行空格进行分隔开。

Redis
Cluster(官方):无中心化设计,程序难以编写;代码有点吓人,clusterProcessPacket函数发426行,人脑难以处理所有的状态切换;迟迟没专业版本,等了4年之悠久;目前还缺最佳实践,没有丁编写Redis
Cluster的多少条注意事项;整个系统高度耦合,升级困难。

(四) OOP规约

1.
【强制】避免通过一个类似的靶子引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。

  1. 【强制】所有的覆写方法,必须加@Override注解。

  反例:getObject()与get0bject()的题目。一个凡字母的O,一个是数字的0,加@Override可以精确判断是否覆盖成功。另外,如果当架空类吃针对艺术签名进行改动,其实现类会马上编译报错。
3.
【强制】相同参数类型,相同业务含义,才足以利用Java的可变参数,避免使用Object。

  说明:可转移参数必须放在参数列表的终极。(提倡同学等尽可能不用而转换参数编程)

  正例:public User getUsers(String type, Integer… ids)
4.
【强制】对外暴露的接口签名,原则及不允许修改章程签名,避免对接口调用方产生潜移默化。接口过时必须加@Deprecated注解,并清晰地说明下的初接口或者新劳动是啊。

  1. 【强制】不能够以老式的切近还是方式。

  说明:java.net.URLDecoder 中的方decode(String encodeStr)
这个方式都不合时宜,应该使用对参数decode(String source, String
encode)。接口提供方既然明确是不合时宜接口,那么来分文不取而提供新的接口;作为调用方来说,有白去考证过时方法的初实现是呀。
6.
【强制】Object的equals方法好抛空指针异常,应利用常量或规定有值的对象来调用equals。

  正例: “test”.equals(object); 反例: object.equals(“test”);

  说明:推荐下java.util.Objects#equals (JDK7引入的工具类)
7.
【强制】所有的均等类别的包装类对象之间值的于,全部以equals方法较。

  说明:对于Integer
var=?在-128届127间的赋值,Integer对象是在IntegerCache.cache产生,会复用已来目标,这个距离内的Integer值可以直接行使==进行判断,但是是区间之外的持有数据,都见面在积上出,并无会见复用已产生对象,这是一个大坑,推荐使用equals方法开展判定。

  1. 【强制】关于中心数据列以及包装数据类型的应用专业如下:

  1) 所有的POJO类属性必须以包装数据类型。

  2) RPC方法的返回值和参数必须动包装数据类型。

  3) 所有的局部变量【推荐】使用基本数据类。

  说明:POJO类属性没有初值是抛砖引玉使用者在急需使用时,必须团结显式地开展赋值,任何NPE问题,或者入库检查,都由使用者来保证。
正例:数据库的询问结果或者是null,因为电动拆箱,用基本数据列接收有NPE风险。

  反例:比如显示成交总额涨跌情况,即正负x%,x为主干数据列,调用的RPC服务,调用不成功时,返回的是默认值,页面显示:0%,这是免成立之,应该出示成中写道-。所以包装数据类型的null值,能够代表额外的信,如:远程调用失败,异常退出。

  1. 【强制】定义DO/DTO/VO等POJO类时,不要设定任何属性默认值。

  反例:POJO类的gmtCreate默认值为new
Date();但是是特性在数据提取时连没置入具体值,在更新任何字段时还要顺手更新了此字段,导致创建时间吃改动成时日子。
10.
【强制】序列化类新增属性时,请不要涂改serialVersionUID字段,避免倒序列失败;如果完全不配合升级,避免反序列化混乱,那么请修改serialVersionUID值。

  说明:注意serialVersionUID不一致会抛来序列化运行时杀。
11.
【强制】构造方法里面禁止参加其他事情逻辑,如果发生初始化逻辑,请在init方法吃。

  1. 【强制】POJO类必须写toString方法。使用IDE的饱受工具:source>
    generate
    toString时,如果连续了另外一个POJO类,注意在面前加一下super.toString。

  说明:在方式执行抛来很时,可以直接调用POJO的toString()方法打印其属于性值,便于排查问题。
13.
【推荐】使用索引访问用String的split方法赢得的数组时,需召开最后一个相隔符后产生管内容之检查,否则会产生抛IndexOutOfBoundsException的风险。
  说明:
    String str = “a,b,c,,”;
    String[] ary = str.split(“,”);
    //预期大于3,结果是3
    System.out.println(ary.length);
14.
【推荐】当一个看似产生多个构造方法,或者基本上个同名方法,这些方式应该遵循顺序放置于齐,便于阅读。

  1. 【推荐】 类内方法定义顺序依次是:公有方法或者护方法 > 私有方法
    > getter/setter方法。
    说明:公有方法是相近的调用者和支持者最关切的主意,首屏展示最好好;保护方法虽然只是子类关心,也可能是“模板设计模式”下之主导措施;而个人方法外部一般不待专门关爱,是一个黑盒实现;因为方法信息价值比较逊色,所有Service和DAO的getter/setter方法放在类体最后。
    16.
    【推荐】setter方法中,参数名称和类似成员变量名称一致,this.成员名=参数称。在getter/setter方法中,尽量不要增加业务逻辑,增加排查问题之难度。

  反例:

public Integer getData() {
        if (true) {
            return data + 100;
        } else {
            return data - 100;
        }
    }

17.
【推荐】循环体内,字符串的属方式,使用StringBuilder的append方法开展扩张。
反例:

String str = "start";
for (int i = 0; i < 100; i++) {
    str = str + "hello";
}

说明:反编译出的字节码文件显示每次循环都见面new出一个StringBuilder对象,然后开展append操作,最后经过toString方法返回String对象,造成内存资源浪费。

  1. 【推荐】final可增进程序响应效率,声明成final的气象:

  1) 不需重赋值的变量,包括类属性、局部变量。

  2) 对象参数前加final,表示不允许修改引用的指向。

  3) 类方法确定不同意为重写。

  1. 【推荐】慎用Object的clone方法来拷贝对象。

  说明:对象的clone方法默认是浅拷贝,若想实现深拷贝需要再次写clone方法实现属性对象的正片。

  1. 【推荐】类成员及方法访问控制从严:

  1) 如果不允许外部直接通过new来创建对象,那么构造方法必须是private。

  2) 工具类不允发生public或default构造方法。

  3) 类非static成员变量并且与子类共享,必须是protected。

  4) 类非static成员变量并且仅于本类使用,必须是private。

  5) 类static成员变量如果单纯于本类使用,必须是private。

  6) 若是static成员变量,必须考虑是不是也final。

  7) 类成员方法只有供类内部调用,必须是private。

  8) 类成员方法才对继承类公开,那么限制为protected。

  说明:任何类、方法、参数、变量,严控访问范围。过广泛的拜访范围,不便宜模块解耦。

  思考:如果是一个private的计,想抹就去,可是一个public的Service方法,或者一个public的成员变量,删除一下,不得手心冒点汗吗?变量像自己之少儿,尽量以协调的视线内,变量作用域太可怜,如果无界定的大街小巷乱跑,那么你会担心之。

尽管如此咱发出诸多的选,比如Tair、Couchbase等,但是要您用再次扑朔迷离与出色的数据结构,Redis可称为不次之选。基于这个缘故,在Redis之上,豌豆荚设计了Codis,并将之开源。

(五) 集合处理

  1. 【强制】关于hashCode和equals的拍卖,遵循如下规则:

  1) 只要再写equals,就亟须重新写hashCode。

  2)
因为Set存储的凡无重的目标,依据hashCode和equals进行判断,所以Set存储的靶子要另行写这片个办法。

  3) 如果由定义对象做吗Map的键,那么要另行写hashCode和equals。

    正例:String重写了hashCode和equals方法,所以我们好生快地利用String对象作为key来使用。

  1. 【强制】
    ArrayList的subList结果不可强转成ArrayList,否则会丢掉来ClassCastException异常:java.util.RandomAccessSubList
    cannot be cast to java.util.ArrayList ;

  说明:subList 返回的是 ArrayList 的内类 SubList,并无是 ArrayList
,而是 ArrayList
的一个视图,对于SubList子列表的有操作最终见面体现到本列表上。

  1. 【强制】
    在subList场景中,高度注意对原集合元素个数的修改,会导致子列表的遍历、增加、删除均产生ConcurrentModificationException
    异常。
  2. 【强制】使用集合转数组的方法,必须使集合的toArray(T[]
    array),传入的凡种完全相同的反复组,大小就是list.size()。

  反例:直接运用toArray无参方法在问题,此措施返回值只能是Object[]仿佛,若高转其它项目数组将应运而生ClassCastException错误。

  正例:

List<String> list = new ArrayList<String>(2);
list.add("guan");
list.add("bao");
String[] array = new String[list.size()];
array = list.toArray(array);

说明:使用toArray带参方法,入参分配的数组空间不足够充分时,toArray方法中用重新分配内存空间,并回到新数组地址;如果频繁组元素大于实际所要,下标为[
list.size()
]的数组元素以于置为null,其它数组元素保持原值,因此最好好拿艺术可参数组大小定义和集合元素个数一致。

5.
【强制】使用工具类Arrays.asList()把数组转换成集时,不克动用其修改集合相关的艺术,它的add/remove/clear方法会抛出UnsupportedOperationException异常。

  说明:asList的回对象是一个Arrays内部类,并不曾实现集的改动章程。Arrays.asList体现的凡适配器模式,只是转换接口,后台的数码以是数组。
String[] str = new String[] { “a”, “b” }; List list =
Arrays.asList(str);

  第一栽状态:list.add(“c”); 运行时老。

  第二种情况:str[0]= “gujin”; 那么list.get(0)也会就修改。

  1. 【强制】泛型通配符<? extends
    T>来接受返回的数额,此写法的泛型集合不克运用add方法。

  说明:苹果装箱后归来一个<? extends
Fruits>对象,此目标就非可知望里加别水果,包括苹果。
7.
【强制】不要以foreach循环里进行元素的remove/add操作。remove元素请以Iterator方式,如果出现操作,需要对Iterator对象加锁。

  反例:

List<String> a = new ArrayList<String>();
a.add("1");
a.add("2");
for (String temp : a) {
    if ("1".equals(temp)) {
        a.remove(temp);
    }
}

证:以上代码的施行结果肯定会压倒大家之预期,那么试一下把“1”换成“2”,会是均等的结果为?
正例:

Iterator<String> it = a.iterator();
while (it.hasNext()) {
    String temp = it.next();
    if (删除元素的条件) {
        it.remove();
    }
}
  1. 【强制】
    在JDK7版本以以上,Comparator要满足自反性,传递性,对称性,不然Arrays.sort,Collections.sort会报IllegalArgumentException异常。

  说明:

  1) 自反性:x,y的于结实以及y,x的可比结实相反。

  2) 传递性:x>y,y>z,则x>z。

  3) 对称性:x=y,则x,z比较结实跟y,z比较结实一律。

  反例:下例中绝非处理等的景况,实际行使中或许会见出现异常:

new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getId() > o2.getId() ? 1 : -1;
    }
}
  1. 【推荐】集合初始化时,尽量指定集合初始值大小。
    说明:ArrayList尽量使用ArrayList(int initialCapacity) 初始化。

  2. 【推荐】使用entrySet全勤历Map类集合KV,而无是keySet方式开展遍历。

  说明:keySet其实是遍历了2次于,一坏是转为Iterator对象,另一样差是起hashMap中取出key所对应的value。而entrySet只是遍历了一如既往软就将key和value都放至了entry中,效率还强。如果是JDK8,使用Map.foreach方法。

  正例:values()返回的是V值集合,是一个list集合对象;keySet()返回的凡K值集合,是一个Set集合对象;entrySet()返回的凡K-V值组合集合。

  1. 【推荐】高度注意Map类集合K/V能不可知积存null值的情事,如下表:
集合类 Key Value Super 说明
Hashtable 不允许为null 不允许为null Dictionary 线程安全
ConcurrentHashMap 不允许为null 不允许为null AbstractMap 分段锁技术
TreeMap 不允许为null 允许为null AbstractMap 线程不安全
HashMap 允许为null 允许为null AbstractMap 线程不安全

 

 

 

 

  反例:
由于HashMap的搅和,很多人数认为ConcurrentHashMap是足以置入null值,注意存储null值时会抛出NPE异常。
12.
【参考】合理采取好聚的有序性(sort)和平静(order),避免集合的无序性(unsort)和非稳定(unorder)带来的负面影响。

  说明:稳定性指集每次遍历的素次序是早晚的。有序性是借助遍历的结果是按部就班某种比较规则依次排列的。如:ArrayList是order/unsort;HashMap是unorder/unsort;TreeSet是order/sort。
13.
【参考】利用Set元素唯一的风味,可以迅速对一个汇聚进行去重操作,避免采取List的contains方法进行遍历、对比、去重操作。

Codis

(六) 并发处理

  1. 【强制】获取单例对象需要保证线程安全,其中的计吗要是包线程安全。

  说明:资源驱动类、工具类、单例工厂类都用注意。

  1. 【强制】创建线程或丝程池时请指定出意义的线程名称,方便出错时回顾。

  正例:

public class TimerTaskThread extends Thread {
    public TimerTaskThread(){
    super.setName("TimerTaskThread"); 
    ...
}
  1. 【强制】线程资源要经过线程池提供,不容许以使用被活动显式创建线程。

  说明:使用线程池的补益是压缩在创造与销毁线程上所消费之年月以及系统资源的开,解决资源不足的题目。如果不使用线程池,有或引致系统创造大气同类线程而致使消耗了内存还是“过度切换”的题目。

  1. 【强制】线程池不同意以
    Executors去创造,而是经过ThreadPoolExecutor去创造,这样的处理方式让写同学尤其简明线程池运行规则,避资源耗尽风险。

  说明: Executors返回的线程池对象的坏处如下 :

  1)FixedThreadPool和 SingleThread:

    允许的伸手队列长度也
Integer.MAX_VALUE,可能会见堆积大量的要,从而致使 OOM。

  2)CachedThreadPool和 ScheduledThreadPool: 允许的缔造线程数量也
Integer.MAX_VALUE,可能会见创造大气之线程,从而造成 OOM。

  1. 【强制】SimpleDateFormat
    是线程不安全的接近,一般不要定义也static变量,如果定义也static,必须加锁,或者用DateUtils工具类。

  正例:注意线程安全,使用DateUtils。亦推荐如下处理:

private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
    @Override
    protected DateFormat initialValue() {
        return new SimpleDateFormat("yyyy-MM-dd");
    }
 }

征:如果是JDK8的使用,可以下Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替Simpledateformatter,官方给闹底分解:simple
beautiful strong immutable thread-safe。

6.
【强制】高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁;能锁区片,就不用锁整个方法体;能就此对象锁,就甭因此类锁。
7.
【强制】对多独资源、数据库表、对象又加锁时,需要保持一致的加锁顺序,否则可能会见造成死锁。

  说明:线程一需要对表A、B、C依次整加锁后才可以进行创新操作,那么线程二的加锁顺序吧要是A、B、C,否则恐怕出现死锁。
8.
【强制】并发修改同一记录时,避免更新丢失,要么在应用层加锁,要么以缓存加锁,要么在数量库层使用乐观锁,使用version作为创新依据。

  说明:如果老是访冲突概率小于20%,推荐使用乐观锁,否则用悲观锁。乐观锁的重试次数不得低于3赖。
9.
【强制】多线程并行处理定时任务时,Timer运行多独TimeTask时,只要中之一没有捕获抛来的百般,其它任务就是会活动终止运行,使用ScheduledExecutorService则没有此问题。
10.
【推荐】使用CountDownLatch进行异步转移同步操作,每个线程退出前须调用countDown方法,线程执行代码注意catch异常,确保countDown方法好推行,避免主线程无法履行及countDown方法,直到超时才回结果。

  说明:注意,子线程抛出非常堆栈,不能够在主线程try-catch及。
11.
【推荐】避免Random实例被多线程使用,虽然共享该实例是线程安全之,但会盖竞争同一seed
导致的性质降低。
  说明:Random实例包括java.util.Random 的实例或者 Math.random()实例。

  正例:在JDK7之后,可以一直下API ThreadLocalRandom,在
JDK7之前,可以做到每个线程一个实例。

  1. 【推荐】通过再检查锁(double-checked
    locking)(在起场景)实现延迟初始化的优化问题隐患(可参考 The
    “Double-Checked Locking is Broken”
    Declaration),推荐问题解决方案面临较为简单一种(适用于JDK5及以上版本),将目标属性声明也
    volatile型。

反例:

class Foo {
    private Helper helper = null;

    public Helper getHelper() {
        if (helper == null)
            synchronized (this) {
                if (helper == null)
                    helper = new Helper();
            }
        return helper;
    }
    // other functions and members...
}

13.
【参考】volatile解决多线程内存不可见问题。对于同状多读,是好化解变量同步问题,但是要是多写,同样无法化解线程安全问题。如果是count++操作,使用如下类实现:AtomicInteger
count = new AtomicInteger(); count.addAndGet(1);
如果是JDK8,推荐下LongAdder对象,比AtomicLong性能更好(减少乐观锁的重试次数)。

  1. 【参考】
    HashMap在容量不足够进行resize时出于高并发可能出现死链,导致CPU飙升,在支付过程中注意避开之风险。
    15.
    【参考】ThreadLocal无法解决共享对象的翻新问题,ThreadLocal对象建议下static修饰。这个变量是指向一个线程内拥有操作共有的,所以设置也静态变量,所有此类实例共享此静态变量
    ,也就是说在近似第一次于吃应用时装载,只分红一片存储空间,所有此类的靶子(只要是其一线程内定义的)都可以操控这个变量。

既还设计,那么Codis首先得满足自动扩容和缩容的需要,其次则是须避免单点故障和单点带富不足,做一个胜可用之网。在马上以后,基于原有的遗留系统,还须得轻松地用数据从Twemproxy迁移到Codis,并落实美好的运维及监控。基于这些,Codis的计划性跃然纸面:

(七) 控制语句

1.
【强制】在一个switch块内,每个case要么通过break/return等来歇,要么注释说明程序将继续执行到啊一个case为止;在一个switch块内,都必含有一个default语句子以位居最后,即使其什么代码也未尝。
2.
【强制】在if/else/for/while/do语句被要利用大括哀号,即使只有来一行代码,避免使用下的款式:if
(condition) statements;

  1. 【推荐】推荐尽量少用else, if-else的措施可改写成:
      if(condition){
        …
        return obj;
      }
      // 就写else的事情逻辑代码;
      说明:如果无得使用if()…else
    if()…else…方式发挥逻辑,【强制】请无超过3层,超过请动状态设计模式。
      正例:逻辑上跳3交汇的if-else代码可以采取卫语句,或者状态模式来兑现。
    4.
    【推荐】除常用方法(如getXxx/isXxx)等他,不要当规则判断中尽外复杂的语句,将复杂逻辑判断的结果赋值给一个发生义的布尔变量名,以增长可读性。

  说明:很多if语句内之逻辑相当复杂,阅读者需要分析条件表达式的最终结出,才能够一目了然哪些的口径执行什么样的口舌,那么,如果阅读者分析逻辑表达式错误为?

  正例:
    //伪代码如下
    boolean existed = (file.open(fileName, “w”) != null) && (…) ||
(…);
    if (existed) {
      …
    }
  反例:
    if ((file.open(fileName, “w”) != null) && (…) || (…)) {
      …
    }
5.
【推荐】循环体中的讲话如果考量性能,以下操作尽量移至循环体外处理,如定义对象、变量、获取数据库连接,进行不必要的try-catch操作(这个try-catch是否足以转换至循环体外)。

  1. 【推荐】接口入参保护,这种场面常见的凡用来做批量操作的接口。
  2. 【参考】方法被要开展参数校验的气象:

  1) 调用频次低之道。

  2)
执行时开很老的艺术,参数校验时间几乎可忽略不计,但如若因参数错误造成中执行回退,或者不当,那得不偿失。
  3) 需要极高稳定性以及可用性的办法。

  4) 对外提供的开接口,不管是RPC/API/HTTP接口。
  5) 敏感权限入口。

  1. 【参考】方法被未待参数校验的场面:

  1)
极有或受循环调用的措施,不建议针对参数进行校验。但以章程求证里要注明外部参数检查。

  2)
底层的办法调用频度都比大,一般不校验。毕竟是像纯净和滤的结尾一鸣,参数错误不太可能到底层才见面暴露问题。一般DAO层与Service层都于同一个运中,部署在平台服务器中,所以DAO的参数校验,可以大概。

  3)
被声称成private只见面让自己代码所调用的不二法门,如果会规定调用方法的代码传入参数已经召开了检查或者自然不见面出题目,此时足免校验参数。

澳门美高梅手机网站 2

(八) 注释规约

1.
【强制】类、类性质、类措施的注解必须利用Javadoc规范,使用/**内容*/格式,不得以//xxx方式。

  说明:在IDE编辑窗口中,Javadoc方式会唤醒相关注释,生成Javadoc可以是输出相应注释;在IDE中,工程调用方法时,不上艺术即可上浮提示方法、参数、返回值的含义,提高阅读效率。
2.
【强制】所有的抽象方法(包括接口中之点子)必须要因此Javadoc注释、除了回到值、参数、异常说明外,还须指出该办法做什么工作,实现啊意义。

  说明:对子类的实现要求,或者调用注意事项,请一并证实。

  1. 【强制】所有的好像都不能不抬高创建者信息。
    4.
    【强制】方法中单行注释,在受诠释语句上方另于一行,使用//注释。方法中多行注释使用/*
    */注释,注意和代码对同。
  2. 【强制】所有的枚举类型字段必须使发生注释,说明每个数据项的用途。
    6.
    【推荐】与那个“半吊子”英文来诠释,不如用中文注释把问题说知道。专有名词与第一字保持英文原文即可。

  反例:“TCP连接超时”解释成“传输控制协议连接超时”,理解反而费脑筋。
7.
【推荐】代码修改的又,注释也要拓展相应的修改,尤其是参数、返回值、异常、核心逻辑等之改。

  说明:代码和注释更新不齐,就像路网和导航软件更新不同台同,如果导航软件严重落后,就失去了领航的义。

  1. 【参考】注释掉的代码尽量使配合征,而未是简约的注释掉。

  说明:代码被诠释掉起个别种可能性:

    1)后续会回升是段子代码逻辑。

    2)永久非用。前者如果无备注信息,难以知晓注释动机。后者建议直接删掉(代码仓库保存了历史代码)。

  1. 【参考】对于注释的要求:

  第一、能够精确反应设计思想和代码逻辑;

  第二、能够描述业务含义,使别的程序员能够快了解及代码背后的音讯。完全无注释的大段代码对于阅读者形同天书,注释是给协调拘留之,即使相隔好丰富日子,也能够清楚明了这底笔触;注释也是被后代看的,使该能迅速接替自己之行事。
10.
【参考】好的命名、代码结构是从说的,注释力求言简意赅准确、表达好。避免出现注释的一个最为:过多过滥的注解,代码的逻辑一旦修改,修改注释是相当好的背。

反例:
  // put elephant into fridge
  put(elephant, fridge);
办法名put,加上两独出义之变量名elephant和fridge,已经认证了立是在干啊,语义清晰的代码不需分外的注解。
11.
【参考】特殊注释标记,请注明标记人同标记时间。注意及时处理这些标记,通过标记扫描,经常清理此类标记。线达故障有时候即使源于这些标记处的代码。

  1) 待办事宜(TODO):( 标记人,标记时间,[展望处理时])
表示要实现,但时还不落实之效果。这实际是一个Javadoc的签,目前的Javadoc还并未兑现,但曾让大规模利用。只能使于类,接口和道(因为它们是一个Javadoc标签)。
  2) 错误,不克工作(FIXME):(标记人,标记时间,[展望处理时])
在诠释中之所以FIXME标记之一代码是谬误的,而且无能够做事,需要立即改正的状。

唯独,一个初系的支出并无是桩好的事情,特别是一个犬牙交错的分布式系统。刘奇代表,虽然就团队才来3单人口,但是她们几考量了可考量的各种细节:

(九) 其它

1.
【强制】在动用正则表达式时,利用好该预编译功能,可以有效加快正则相当速度。

  说明:不要在点子体内定义:Pattern pattern = Pattern.compile(规则);
2.
【强制】velocity调用POJO类的性能时,建议直接动用属性名取值即可,模板引擎会自动按规范调用POJO的getXxx(),如果是boolean基本数据类变量(boolean命名不需要加is前缀),会自动调用isXxx()方法。

  说明:注意要是Boolean包装类对象,优先调用getXxx()的艺术。

  1. 【强制】后大输送给页面的变量必须加$!{var}——中间的感叹号。

  说明:如果var=null或者未有,那么${var}会直接显示在页面上。

  1. 【强制】注意 Math.random() 这个主意返回是double类型,注意取值的限定
    0≤x<1(能够获取到零值,注意除散装不行),如果想得整数列的任性数,不要拿x放大10底几何倍然后取整,直接使用Random对象的nextInt或者nextLong方法。
  2. 【强制】获取当前毫秒数System.currentTimeMillis(); 而不是new
    Date().getTime();

  说明:如果想得更纯粹的纳秒级时间价值,用System.nanoTime()。在JDK8饱受,针对统计时等景象,推荐应用Instant类。
6.
【推荐】尽量不要以vm中进入变量声明、逻辑运算符,更不用在vm模板被入其他复杂的逻辑。
7.
【推荐】任何数据结构的组织或初始化,都许诺指定大小,避免数据结构无限增长吃光内存。
8.
【推荐】对于“明确停止使用的代码和安排”,如方法、变量、类、配置文件、动态配置属性等而坚决打程序中清理出去,避免造成过多垃圾。

  • 尽可能拆分,简化每个模块,同时爱升级
  • 每个组件只负责协调的事体
  • Redis只当作存储引擎
  • Proxy的状态
  • Redis故障判定是否坐外部,因为分布式系统存活的判断异常复杂
  • 提供API让外部调用,当Redis Master丢失时,提升Slave为Master
  • 图形化监控整个:slot状态、Proxy状态、group状态、lock、action等等

仲、异常日志

只要以踏勘了整套事务后,另一个争辩摆在了前方——Proxy或者是Smart Client:Proxy拥有更好的监察及控制,同时该后端信息也是暴露,易于升级;而Smart Client拥有再好的性质,及重新没有之延时,但是升级起来也较辛苦。对比种种优劣,他们最终摘取了Proxy,无独有偶,在codis开源后,twitter的一个享受提到他们也是基于proxy的筹划。

(一) 异常处理

1.
【强制】不要捕获Java类库中定义之连续自RuntimeException的运作时颇类,如:IndexOutOfBoundsException
/ NullPointerException,这好像非常由程序员预检查来逃避,保证程序健壮性。

  正例:if(obj != null) {…}

  反例:try { obj.method() } catch(NullPointerException e){…}
2.
【强制】异常不要为此来做流程控制,条件决定,因为很的拍卖效率比标准划分支低。
3.
【强制】对大段代码进行try-catch,这是不负责任的表现。catch时请分清稳定代码和未稳定代码,稳定代码指的凡无论如何不会见拧的代码。对于不稳定代码的catch尽可能进行区分好类型,再开相应之不得了处理。
4.
【强制】捕获异常是以处理它,不要捕获了可什么还未处理要抛开的,如果不思量处理它,请将拖欠老抛给她的调用者。最外层的作业使用者,必须处理好,将该转会为用户可以了解的内容。
5.
【强制】有try块放到了作业代码中,catch异常后,如果欲回滚事务,一定要是专注手动回滚事务。
6.
【强制】finally块必须对资源对象、流对象开展关闭,有不行与否如举行try-catch。

  说明:如果JDK7,可以下try-with-resources方式。
7.
【强制】不能够在finally块中使用return,finally块中之return返回后措施了执行,不见面再实施try块中的return语句。
8.
【强制】捕获异常及抛大,必须是全然配合,或者捕获异常是抛弃大的父类。

  说明:如果预想对方抛的是绣球,实际收到的是铅球,就会见出意想不到情况。
9.
【推荐】方法的返回值可以啊null,不愈制返回空集合,或者空对象等,必须加加注充分说明什么情况下会回来null值。调用方需要开展null判断防止NPE问题。

  说明:本规约明确防止NPE是调用者的责任。即使被调用方法返回空集合或者空对象,对调用者来说,也休想高枕无忧,必须考虑到长途调用失败,运行时好等景象返回null的状态。

  1. 【推荐】防止NPE,是程序员的主干修养,注意NPE产生的状况:

  1) 返回路也包装数据类型,有或是null,返回int值时注意判空。

    反例:public int f(){ return Integer对象};
如果为null,自动解箱抛NPE。

  2) 数据库的查询结果或者也null。

  3) 集合里的因素就是isNotEmpty,取有的数量元素也可能啊null。
  4) 远程调用返回对象,一律要求开展NPE判断。

  5) 对于Session中得之多少,建议NPE检查,避免空指针。

  6) 级联调用obj.getA().getB().getC();一连串调用,易起NPE。
11.
【推荐】在代码中使“抛大”还是“返回错误码”,对于公司外的http/api开放接口必须使用“错误码”;而使用中推荐生抛来;跨应用间RPC调用优先考虑下Result方式,封装isSuccess、“错误码”、“错误简短信息”。
说明:关于RPC方法返回方式使用Result方式的理:

  1)使用抛大返回方式,调用方如果没捕获到即会见产生运行时不当。

  2)如果非加以库信息,只是new自定义格外,加入自己之知道的error
message,对于调用端解决问题的帮带不见面太多。如果加了储藏室信息,在勤调用出错的情形下,数据序列化和导的特性损耗也是题材。

  1. 【推荐】定义时区分unchecked / checked
    异常,避免直接采用RuntimeException抛来,更不允许抛出Exception或者Throwable,应以有作业含义的自定义异常。推荐业界已定义了的自定义异常,如:DAOException
    / ServiceException等。
  2. 【参考】避免出现重复的代码(Don’t Repeat Yourself),即DRY原则。
    说明:随意复制和糊代码,必然会招致代码的重,在后用修改时,需要改所有的副本,容易遗漏。必要经常抽取共性方法,或者抽象公共类,甚至是一道用模块。

  正例:一个类似中发生多单public方法,都需开展数行相同之参数校验操作,这个时候要抽取:
  private boolean checkParam(DTO dto){…}

澳门美高梅手机网站 3

(二) 日志则

1.
【强制】应用被不可直接以日志系统(Log4j、Logback)中之API,而应借助于使用日志框架SLF4J中的API,使用门面模式之日记框架,有利于维护及各个类的日记处理方式统一。
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  private static final Logger logger =
LoggerFactory.getLogger(Abc.class);
2.
【强制】日志文件推荐至少保存15天,因为有些死具备为“周”为频次发生的性状。
3.
【强制】应用中之壮大日志(如打点、临时监控、访问日志对等)命名方式:appName_logType_logName.log。logType:日志类型,推荐分类有stats/desc/monitor/visit等;logName:日志描述。这种命名的补:通过文件称就是不过掌握日记文件属于什么使,什么项目,什么目的,也造福归类查找。

  正例:mppserver应用中独立监控时区转换异常,如:
mppserver_monitor_timeZoneConvert.log
说明:推荐对日记进行分拣,错误日志与作业日志尽量分开存放,便于开发人员查看,也惠及通过日记对系进行即时监督。
4.
【强制】对trace/debug/info级别的日志输出,必须动规则输出形式还是用占位符的法。

  说明:logger.debug(“Processing trade with id: ” + id + ” symbol: ” +
symbol);
如果日志级别是warn,上述日志不会见打印,但是会履行字符串拼接操作,如果symbol是目标,会实施toString()方法,浪费了系统资源,执行了上述操作,最终日志也从不打印。

  正例:(条件)
  if (logger.isDebugEnabled()) {
    logger.debug(“Processing trade with id: ” + id + ” symbol: ” +
symbol);
  }
  正例:(占位符)
  logger.debug(“Processing trade with id: {} symbol : {} “, id,
symbol);
5.
【强制】避免重复打印日志,浪费磁盘空间,务必于log4j.xml中安additivity=false。

  正例:<logger name=”com.taobao.dubbo.config”
additivity=”false”>
6.
【强制】异常信息应该包括个别接近消息:案发现场信息以及良堆栈信息。如果不处理,那么向上扔。

  正例:logger.error(各类参数或者目标toString + “_” + e.getMessage(),
e);
7.
【推荐】可以行使warn日志级别来记录用户输入参数错误的图景,避免用户投诉时,无所适从。注意日志输出的级别,error级别只记录系统逻辑出错、异常等重大的错误信息。如无必不可少,请不要以这个现象打来error级别。
8.
【推荐】谨慎地记下日志。生产条件禁止出口debug日志;有选择地出口info日志;如果应用warn来记录刚上线时之作业行为信息,一定要是注意日志输出量的题目,避免将服务器磁盘撑爆,并记这去这些观测日志。

  说明:大量地出口无效日志,不便利系统特性提升,也非便宜快速稳定错误点。记录日志时恳求考虑:这些日记真的有人看吗?看到这漫漫日志你能够举行啊?能无可知给问题排查带来利益?

Codis主要含有Codis Proxy(codis-proxy)、Codis Manager(codis-config)、Codis Redis(codis-server)和ZooKeeper四大组件,每个片还不过动态扩容。

三、MySQL规约

codis-proxy 客户端连接的Redis代理服务,本身实现了Redis协议,表现不行像原生的Redis (就比如 Twemproxy)。一个事情好配备多单 codis-proxy,其自是任状态的。

(一) 建表规约

1.
【强制】表达是也概念的字段,必须使用is_xxx的措施命名,数据类型是unsigned
tinyint( 1表示是,0表示否),此规则平等适用于odps建表。

  说明:任何字段如果也非负数,必须是unsigned。
2.
【强制】表名、字段名必须下小写字母或数字;禁止出现数字开,禁止个别单下划线中间就出现数字。数据库字段名的修改代价十分十分,因为无法开展先期披露,所以字段名称需要慎重考虑。

  正例:getter_admin,task_config,level3_name

  反例:GetterAdmin,taskConfig,level_3_name

  1. 【强制】表名不使复数名词。
    说明:表名应该仅仅意味着表里面的实业内容,不该代表实体数量,对诺受DO类名也是单数形式,符合表达习惯。
    4.
    【强制】禁用保留字,如desc、range、match、delayed等,请参见MySQL官方保留字。
  2. 【强制】唯一索引名为uk_字段名;普通索引名则也idx_字段名。
    说明:uk_ 即 unique key;idx_ 即index的简称。
  3. 【强制】小数类型为decimal,禁止利用float和double。

  说明:float和double在储存的时节,存在精度损失的问题,很可能在值的较时,得到非得法的结果。如果存储的数额范围越decimal的限定,建议以数据拆成整数和小数分开储存。

  1. 【强制】如果存储的字符串长度几乎等于,使用char定长字符串类型。
    8.
    【强制】varchar是不过易长字符串,不事先先分配存储空间,长度不要跨越5000,如果存储长度超过此值,定义字段类型也text,独立出来一摆设表,用主键来对号入座,避免影响其他字段索引效率。
  2. 【强制】表必备三字段:id, gmt_create, gmt_modified。

  说明:其中id必为主键,类型为unsigned
bigint、单表时自增、步长为1。gmt_create,
gmt_modified的种类均为date_time类型。

  1. 【推荐】表的命名最好是长“业务名称_申的来意”。 正例:tiger_task /
    tiger_reader / mpp_config
  2. 【推荐】库名与祭名称尽量一致。
    12.
    【推荐】如果改动字段含义或针对字段表示的状态多时,需要这更新字段注释。
    13.
    【推荐】字段允许适当冗余,以提高性,但是得考虑数据并的情。冗余字段应按照:

  1)不是多次修改的字段。 2)不是varchar超长字段,更非克是text字段。

    正例:商品类目名称使用效率高,字段长度短,名称基本有序,可每当彼此关联的表中冗余存储类目名称,避免关系查询。

  1. 【推荐】单表行数超过500万实行要单表容量超过2GB,才推荐进行分库分表。

  说明:如果预测三年后的数据量根本上不交者级别,请不要在开创表时即使分库分表。
15.
【参考】合适的字符存储长度,不但节约数据库表空间、节约索引存储,更主要之是升级查找速度。

  正例:人之年纪用unsigned
tinyint(表示范围0-255,人的寿命不会见过255寒暑);海龟就得是smallint,但如果是阳光之年,就非得是int;如果是有着恒星的齿都加起,那么尽管亟须采用bigint。

codis-config。Codis 的管理工具,支持添加/删除Redis节点、添加/删除Proxy节点、发起数迁移等操作。codis-config自带了一个http server,会启动一个dashboard,用户可以当浏览器上观赛 Codis 集群的周转状态。

(二) 索引规约

1.
【强制】业务上具有唯一特点的字段,即使是成字段,也务必建成唯一索引。

  说明:不要看唯一索引影响了insert速度,这个速度损耗可以忽略,但提高查找速度是显著的;另外,即使在应用层做了大周到之校验和控制,只要没唯一索引,根据墨菲定律,必然发生肮脏数据来。

  1. 【强制】
    超过三独表禁止join。需要join的字段,数据类型保持绝对平等;多表关联查询时,保证被波及的字段需要发出目录。

  说明:即使双表join也要专注表索引、SQL性能。
3.
【强制】在varchar字段上成立目录时,必须指定索引长度,没必要对全配段建立目录,根据实际文本区分度决定索引长度。

  说明:索引的长度以及区分度是一律对准矛盾体,一般对字符串类型数据,长度为20之目录,区分度会大及90%上述,可以使用count(distinct
left(列名, 索引长度))/count(*)的区分度来确定。

  1. 【强制】页面搜索严禁左模糊或者都模糊,如果欲请动搜索引擎来化解。

  说明:索引文件具有B-Tree的最好荒唐前方缀匹配特性,如果左边的价不规定,那么无法使此索引。

  1. 【推荐】如果生order by的观,请留意利用索引的有序性。order by
    最后的字段是成索引的一模一样片,并且位居索引组合顺序的终极,避免出现file_sort的情况,影响查询性能。

  正例:where a=? and b=? order by c; 索引:a_b_c

  反例:索引中产生限量查找,那么索引有序性无法用,如:WHERE a>10
ORDER BY b; 索引a_b无法排序。

  1. 【推荐】利用覆盖索引来进行询问操作,来避免回表操作。

  说明:如果相同本书用掌握第11回是呀标题,会翻第11章对应之那无异页也?目录浏览一下即好,这个目录就是自从及掩索引的意向。

  正例:能够建立目录的品类:主键索引、唯一索引、普通索引,而覆盖索引是一样种植查询的一律种植功能,用explain的结果,extra列会出现:using
index。

  1. 【推荐】利用延迟关联或者子查询优化超多分页场景。

  说明:MySQL并无是越了offset行,而是取offset+N行,然后返回放弃前offset行,返回N行,那当offset特别酷之时光,效率就够呛的放下,要么控制返回的终究页数,要么对跨一定阈值的页数进行SQL改写。

  正例:先飞稳定要获得的id段,然后又干: SELECT a.* FROM 表1 a,
(select id from 表1 where 条件 LIMIT 100000,20 ) b where a.id=b.id

  1. 【推荐】 SQL性能优化的对象:至少要达标 range
    级别,要求凡ref级别,如果得以是consts最好。

  说明:

    1)consts
单表中极多只出一个匹配行(主键或者唯一索引),在优化等即可读博到数量。

    2)ref 指的是采取普通的目录(normal index)。

  澳门美高梅手机网站  3)range 对索引进行限制检索。

  反例:explain表的结果,type=index,索引物理文件均扫描,速度很缓慢,这个index级别比较range还不及,与全表扫描是小巫见大巫。

  1. 【推荐】建组合索引的时刻,区分度最高的于极其左边。 正例:如果where a=?
    and b=? ,a列的几接近于唯一值,那么就需要单建idx_a索引即可。

  说明:存在非等号和相当号混合判断标准时,在建索引时,请把等号准的列前置。如:where
a>? and b=? 那么就是a的区分度更胜,也必管b放在索引的最好前列。

  1. 【参考】创建索引时避免产生如下极端误解:

  1)误认为一个询问就需要建造一个目。

  2)误认为索引会消耗空间、严重拖慢更新与新增速度。

  3)误认为唯一索引一律要在应用层通过“先翻后插”方式解决。

codis-server。Codis 项目保护的一个Redis分支,加入了slot的支持及原子的数据迁移指令。

(三) SQL规约

1.
【强制】不要动count(列名)或count(常量)来替代count(*),count(*)就是SQL92概念之专业统计行数的语法,跟数据库无关,跟NULL和非NULL无关。

  说明:count(*)会统计值为NULL的推行,而count(列名)不见面统计是列为NULL值的履行。

  1. 【强制】count(distinct col) 计算该列除NULL之外的匪又数量。注意
    count(distinct col1, col2)
    如果中同样列全呢NULL,那么就是其它一样排列有不同的价,也回为0。
    3.
    【强制】当有平排的值都是NULL时,count(col)的归结果吧0,但sum(col)的回结果为NULL,因此用sum()时索要注意NPE问题。

  正例:可以利用如下方式来避免sum的NPE问题:SELECT
IF(ISNULL(SUM(g)),0,SUM(g)) FROM table;
4.
【强制】使用ISNULL()来判定是否也NULL值。注意:NULL与任何值的一直比较还为NULL。

  说明: 1) NULL<>NULL的回结果是NULL,而休是false。

      2) NULL=NULL的回来结果是NULL,而无是true。

        3) NULL<>1之回结果是NULL,而休是true。

  1. 【强制】
    在代码中形容分页查询逻辑时,若count为0答应直接返回,避免执行后的分页语句。
  2. 【强制】不得采取外键与级联,一切外键概念必须在应用层解决。
    说明:(概念解释)学生表中的student_id是主键,那么成绩表中的student_id则也外键。如果更新学生表中的student_id,同时触发成绩表中的student_id更新,则也级联更新。外键与级联更新适用于只机低并发,不符合分布式、高并发集群;级联更新是强阻塞,存在数据库更新风暴的风险;外键影响数据库的插入速度。
  3. 【强制】禁止利用存储过程,存储过程难调试和壮大,更未曾移植性。
    8.
    【强制】数据订正时,删除和改记录时,要先select,避免出现误删除,确认无误才能够实行更新语句。
    9.
    【推荐】in操作会免则免,若实于避免不了,需要精心评估in后止的集合元素数量,控制以1000单里面。
    10.
    【参考】如果生全球化需要,所有的字符存储和代表,均因utf-8编码,那么字符计数方法注意:

  说明: SELECT LENGTH(“轻松工作”); 返回吗12 SELECT
CHARACTER_LENGTH(“轻松工作”); 返回吗4
如果要动表情,那么用utfmb4来进展仓储,注意她与utf-8编码的界别。

  1. 【参考】 TRUNCATE TABLE 比 DELETE
    速度快,且使的体系和工作日志资源少,但TRUNCATE无事务且不触发trigger,有或导致事故,故不建议于出代码中采用这语。

  说明:TRUNCATE TABLE 在职能及同不带 WHERE 子句的 DELETE 语句相同。

ZooKeeper。Codis依赖ZooKeeper来存放数据路由表和codis-proxy节点的处女信息,codis-config发起的命令会通过 ZooKeeper同步到各个存活的codis-proxy。

(四) ORM规约

  1. 【强制】在表查询中,一律不要以 *
    作为查询的字段列表,需要哪字段必须明白写明。

  说明:

    1)增加查询分析器解析成本。

    2)增减配段容易与resultMap配置不相同。
2.
【强制】POJO类的boolean属性不能够加is,而数据库字段必须加is_,要求以resultMap中展开字段与特性之间的照耀。

  说明:参见定义POJO类以及数据库字段定义规定,在sql.xml增加映射,是必须的。
3.
【强制】不要用resultClass当回参数,即使有类属性名与数据库字段一一对应,也用定义;反过来,每一个说明也定有一个与之对应。

  说明:配置映射关系,使字段与DO类解耦,方便维护。

  1. 【强制】xml配置中参数注意使用:#{},#param# 不要使用${}
    此种方式容易并发SQL注入。
  2. 【强制】iBATIS自带的queryForList(String statementName,int start,int
    size)不推荐使用。

  说明:其促成方式是于数据库取到statementName对应的SQL语句的备记录,再经subList取start,size的子集合,线及因为这个原因已经出现过OOM。
正例:在sqlmap.xml中引入 #start#, #size#
  Map<String, Object> map = new HashMap<String,
Object>();
  map.put(“start”, start);
  map.put(“size”, size);

  1. 【强制】不同意直接拿HashMap与Hashtable作为查询结果集的出口。
    7.
    【强制】更新数据表记录时,必须以创新记录对应的gmt_modified字段值为当下日子。
    8.
    【推荐】不要写一个非常如净的数量更新接口,传入为POJO类,不管是无是好的靶子更新字段,都开展update
    table set c1=value1,c2=value2,c3=value3;
    这是颠三倒四的。执行SQL时,尽量不要更新无更改的字段,一凡是容易出错;二凡是效率低;三凡binlog增加存储。
    9.
    【参考】@Transactional事务不要滥用。事务会潜移默化数据库的QPS,另外利用工作的地方需要考虑各方面的回滚方案,包括缓存回滚、搜索引擎回滚、消息补偿、统计修正等。
    10.
    【参考】<isEqual>中的compareValue是同属于性值对比的常量,一般是数字,表示相当时带达之条件;<isNotEmpty>表示未呢空且不为null时实行;<isNotNull>表示不也null值时实施。

澳门美高梅手机网站 4

季、工程则

末,刘奇还介绍详细的了Codis中Migration、lock (rwlock)等操作的实现过程和规律,以及由Twemproxy迁移到Codis的详尽操作。更多Codis详情可移步Clodis开源页
GitHub

(一) 应用分层

1.
【推荐】图被默认上层依赖让下层,箭头关系表示可一直依赖,如:开放接口层可以因让Web层,也可以直接依赖让Service层,依此类推:

开放接口层:可直接封装Service接口暴露成RPC接口;通过Web封装成http接口;网关控制层等。

终端显示层:各个端的模板渲染并推行显示层。当前紧要是velocity渲染,JS渲染,JSP渲染,移动端展示层等。

Web层:主要是针对性访问控制进行转向,各类基本参数校验,或者未复用的政工简单处理等。
 Service层:相对具体的作业逻辑服务层。
 Manager层:通用业务处理层,它发出如下特征:

  1) 对第三着平台封装的叠,预处理回来结果与转账异常信息;

  2) 对Service层通用能力的下浮,如缓存方案、中间件通用处理;

  3) 与DAO层交互,对DAO的事情通用能力的卷入。
 DAO层:数据访问层,与底层MySQL、Oracle、Hbase进行多少交互。

外部接口或第三方平台:包括其他单位RPC开放接口,基础平台,其它企业之HTTP接口。

  1. 【参考】
    (分层异常处理规约)在DAO层,产生的不得了类型有过多,无法用细粒度异常进行catch,使用catch(Exception
    e)方式,并throw new
    DAOException(e),不欲打印日志,因为日志在Manager/Service层一定用捕获并打到日志文件被失去,如果同服务器又从日志,浪费性能和仓储。在Service层出现异常时,必须记录日志信息及磁盘,尽可能带及参数信息,相当给保护案发现场。如果Manager层与Service同机部署,日志方式跟DAO层处理同,如果是独自安排,则使用与Service一致的处理方式。Web层绝不应该继续向上扔大,
    以就处在顶层,无继续处理非常的法子,如果发现及者可怜将致页面无法正常渲染,那么即使该直接跨越反至祥和错误页面,尽量加上自己的错误提示信息。开放接口层要用大处理成错误码和错误信息方式回。
  2. 【参考】分层领域模型规约:
     DO(Data
    Object):与数库表结构一一对应,通过DAO层向上传输数据源对象。
     DTO(Data Transfer
    Object):数据传对象,Service和Manager向他传输的目标。
     BO(Business
    Object):业务对象。可以由Service层输出的卷入业务逻辑的目标。

    QUERY:数据查询对象,各层接收上层的查询请求。注:超过2个参数的询问封装,禁止使用Map类来传。
     VO(View Object):显示层对象,通常是Web向模板渲染引擎层传输的对象。

(二) 二方库规约

  1. 【强制】定义GAV遵从以下规则:

  1) GroupID格式:com.{公司/BU }.业务线.[子业务线],最多4级。

    说明:{公司/BU}
例如:alibaba/taobao/tmall/aliexpress等BU一级;子业务线可选。

    正例:com.taobao.jstorm 或 com.alibaba.dubbo.register

  2)
ArtifactID格式:产品线名-模块名。语义不重复不遗漏,先到库房中心去查一下。

    正例:dubbo-client / fastjson-api / jstorm-tool 3)
Version:详细规定参考下方。

  1. 【强制】二方库版本号命名方式:主版本号.次版本号.修订号

  1) 主版本号:当做了无配合的API
修改,或者增加了力所能及更改产品趋势的新职能。

  2) 次版本号:当做了向下兼容的功能性新增(新增类、接口等)。

  3) 修订号:修复bug,没有改动章程签名的力量增强,保持 API 兼容性。

    说明: 起始版本号 必须 为: 1.0.0,而休是 0.0.1
3.
【强制】线达运不要依赖SNAPSHOT版本(安全保除外);正式颁发的类库必须下RELEASE版本号升级+1的道,且版本号不容许覆盖升级,必须去中央仓库进行调查。

  说明:不依赖SNAPSHOT版本是管应用发布之幂等性。另外,也得以加速编译时的由包构建。
4.
【强制】二方库的激增或提升,保持除功能点以外的任何jar包仲裁结果未转换。如果发生改观,必须旗帜鲜明评估和验证,建议开展dependency:resolve前后信息比对,如果仲裁结果了无一致,那么通过dependency:tree命令,找出差异点,进行<excludes>排除jar包。
5.
【强制】二方库里可以定义枚举类型,参数可以采用枚举类型,但是接口返回值不允许利用枚举类型或者隐含枚举类型的POJO对象。
6.
【强制】依赖让一个二方库群时,必须定义一个联结版本变量,避免版本号不同等。

  说明:依赖springframework-core,-context,-beans,它们还是同一个版本,可以定义一个变量来保存版本:${spring.version},定义依赖的下,引用该版本。
7.
【强制】禁止在子项目之pom依赖中起平之GroupId,相同的ArtifactId,但是不同的Version。

  说明:在该地调试时会见使各子项目指定的版号,但是合并成一个war,只能发出一个版本号出现于终极之lib目录中。曾经出现了线下调试是天经地义的,发布暨丝达发生故障的先例。
8.
【推荐】所有pom文件被的借助声明在<dependencies>语句块被,所有版本仲裁放在<dependencyManagement>语句子块被。

  说明:<dependencyManagement>里只是宣称版本,并无兑现引入,因此子项目用显式的声明指,version和scope都念博自父pom。而<dependencies>所有宣称在主pom的<dependencies>里之赖还见面自行引入,并默认为有着的子项目继承。

  1. 【推荐】二方库尽量不要来布置起,最低限度不要还增部署起。
    10.
    【参考】为避免用二方库的依冲突问题,二方库发布者应当遵循以下规则:

  1)精简可控条件。移除一切非必要之API和依赖性,只包含 Service
API、必要的领域模型对象、Utils类、常量、枚举等。如果借助其它二方库,尽量是provided引入,让二方库使用者去因具体版本号;无log具体贯彻,只靠日志框架。

  2)稳定而追溯原则。每个版本的别应该吃记录,二方库由何人保护,源码在何,都得能好查到。除非用户主动提升版本,否则公共二方库的行未应该发生变化。

(三) 服务器规约

  1. 【推荐】高并发服务器建议调整小TCP协议的time_wait超时时间。
    说明:操作系统默认240秒后,才会关闭处于time_wait状态的接连,在胜并发访问下,服务器端会为远在time_wait的连日数最好多,可能无法树立新的总是,所以需要以服务器上调小此等待值。

  正例:在linux服务器上求通过变更/etc/sysctl.conf文件去窜该少省值(秒):
net.ipv4.tcp_fin_timeout = 30

  1. 【推荐】调大服务器所支持的绝可怜文件句柄数(File
    Descriptor,简写为fd)。

  说明:主流操作系统的宏图是拿TCP/UDP连接使用与公事一律的主意去管理,即一个一连对应于一个fd。主流的linux服务器默认所支持太要命fd数量也1024,当并发连接数很充分时老容易因fd不足而起“open
too many files”错误,导致新的连年无法建立。
建议以linux服务器所支撑之极度充分词柄数调强数加倍(与服务器的内存数量相关)。
3.
【推荐】给JVM设置-XX:+HeapDumpOnOutOfMemoryError参数,让JVM碰到OOM场景时输出dump信息。

  说明:OOM的有是来几率的,甚至发出规律地相隔数月份才面世一样章,出现不时的现场消息对查错非常有价。
4.
【参考】服务器中重定向以forward;外部重定向地方下URL拼装工具类来转,否则会带动URL维护不一样的题目及心腹的安康风险。

五、安全规则

  1. 【强制】隶属于用户个人的页面或者功能必须进行权力决定校验。
    说明:防止没有举行水平权限校验就只是自由走访、操作别人的数据,比如查看、修改别人的订单。
  2. 【强制】用户敏感数据禁止直接展示,必须对展示数据脱敏。
    说明:查看个人手机号码会来得成:158****9119,隐藏中间4各,防止隐私泄露。
    3.
    【强制】用户输入的SQL参数严格使用参数绑定或者METADATA字段值限定,防止SQL注入,禁止字符串拼接SQL访问数据库。
  3. 【强制】用户请求传入的外参数必须做行验证。
    说明:忽略参数校验可能致:
     page size过死招内存溢出
     恶意order by导致数据库慢查询
     任意重定向
     SQL注入
     反序列化注入
     正则输入源串拒绝服务ReDoS 说明: Java JavaJava代码用 代码用
    正则来证实客户端的输入,有些刚则写法验证普通用户输入没有问题,但是要攻击人员动用的凡特种结构之字符串来证实,有或致死循环的意义
  4. 【强制】禁止向HTML页面输出未经安全过滤或非对转义的用户数量。
  5. 【强制】表单、AJAX提交必须实行CSRF安全过滤。 说明:CSRF(Cross-site
    request
    forgery)跨站请求伪造是均等类似常见编程漏洞。对于有CSRF漏洞的应用/网站,攻击者可先构造好URL,只要受害者用户同样访问,后台就以用户不知情情况下本着数据库被用户参数进行相应修改。
    7.
    【强制】在运用平台资源,譬如短信、邮件、电话、下单、支付,必须兑现科学的防重放克,如数量限制、疲劳度控制、验证码校验,避免吃滥刷、资损。

  说明:如注册时发送验证码到手机,如果没限定次数与效率,那么得应用是功效骚扰到另外用户,并致短信平台资源浪费。

发表评论

电子邮件地址不会被公开。 必填项已用*标注