精华内容
下载资源
问答
  • 1.json-lib与Jackson  关于json-lib与... 2).json-lib已经停止更新,最新的版本也是基于JDK1.5,而Jackson的社区则较为活跃。  3).json-lib依赖commons系列的包及ezmorph包共5个,而Jackson除自身的以外只...

    1.json-lib与Jackson

      关于json-lib与Jackson对比总结如下:

      1).性能方面,Jackson的处理能力高出Json-lib10倍左右。

      2).json-lib已经停止更新,最新的版本也是基于JDK1.5,而Jackson的社区则较为活跃。

      3).json-lib依赖commons系列的包及 ezmorph包共 5个,而Jackson除自身的以外只依赖于commons-logging

     

    2.1 Jackson序列化与反序列化方法

     1  public static String encode(Object obj) {
     2         try {
     3             return objectMapper.writeValueAsString(obj);
     4         } catch (Exception e) {
     5             logger.error("jackson encode error:", e); 
     6         }
     7         return null;
     8     }
     9 
    10     /**
    11      * 将json string反序列化成对象
    12      *
    13      * @param json
    14      * @param valueType
    15      * @return
    16      */
    17     public static <T> T decode(String json, Class<T> valueType) {
    18         try {
    19             return objectMapper.readValue(json, valueType);
    20         } catch (Exception e) {
    21             logger.error("jackson decode(String, Class<T>) error: ", e);
    22         }
    23         return null;
    24     }
    25 
    26     /**
    27      * 将json array反序列化为对象
    28      *
    29      * @param json
    30      * @param typeReference
    31      * @return
    32      */
    33     public static <T> T decode(String json, TypeReference<T> typeReference) {
    34         try {
    35             return (T) objectMapper.readValue(json, typeReference);
    36         } catch (Exception e) {
    37             logger.error("decode(String, JsonTypeReference<T>)", e);
    38         }
    39         return null;
    40     }
    View Code

     2.2 Jackson自动检测机制

       jackson默认的字段属性发现规则如下:

        所有被public修饰的字段->所有被public修饰的getter->所有被public修饰的setter

      若类中的一个private属性,且没有设置public的getter和setter方法,则对该类对象进行序列化时,默认不对这个private属性进行序列化。

      若此时任然需要对该private属性进行序列化,可以通过设置自动检测功能来实现:

      2.2.1 通过配置属性实现

    1 objectMapper
    2             .setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY) // 自动检测所有类的全部属性
    3             .setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.ANY) //自动检测所有类的public getter方法
    4        .setVisibility(PropertyAccessor.IS_GETTER, JsonAutoDetect.Visibility.ANY); //自动检测所有类的public setter方法
    View Code

      2.2.2 使用@JsonAutoDetect(作用在类上)来开启/禁止自动检测  

        fieldVisibility:字段的可见级别

        ANY:任何级别的字段都可以自动识别

        NONE:所有字段都不可以自动识别

        NON_PRIVATE:非private修饰的字段可以自动识别

        PROTECTED_AND_PUBLIC:被protected和public修饰的字段可以被自动识别

        PUBLIC_ONLY:只有被public修饰的字段才可以被自动识别

        DEFAULT:同PUBLIC_ONLY

      @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) 

    3.序列化与反序列化属性总结

      与json-lib相比,Jackson在序列化与反序列时,可以对序列化与反序列化进行配置,是的输出结果满足自己的要求。序列化与反序列化属性很多,下面对一些常用属性进行介绍。

      3.1 序列化属性  

            //这个特性,决定了解析器是否将自动关闭那些不属于parser自己的输入源。
            // 如果禁止,则调用应用不得不分别去关闭那些被用来创建parser的基础输入流InputStream和reader;
            //默认是true
            objectMapper.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, true);
            //是否允许解析使用Java/C++ 样式的注释(包括'/'+'*' 和'//' 变量)
            objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
    
            //设置为true时,属性名称不带双引号
            objectMapper.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false);
            //反序列化是是否允许属性名称不带双引号
            objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
    
            //是否允许单引号来包住属性名称和字符串值
            objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
    
            //是否允许JSON字符串包含非引号控制字符(值小于32的ASCII字符,包含制表符和换行符)
            objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
    
            //是否允许JSON整数以多个0开始
            objectMapper.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true);
    
            //null的属性不序列化
            objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    
            //按字母顺序排序属性,默认false
            objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY,true);
    
            //是否以类名作为根元素,可以通过@JsonRootName来自定义根元素名称,默认false
            objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE,true);
    
            //是否缩放排列输出,默认false
            objectMapper.configure(SerializationFeature.INDENT_OUTPUT,false);
    
            //序列化Date日期时以timestamps输出,默认true
            objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,true);
    
            //序列化枚举是否以toString()来输出,默认false,即默认以name()来输出
            objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
    
            //序列化枚举是否以ordinal()来输出,默认false
            objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_INDEX,false);
    
            //序列化单元素数组时不以数组来输出,默认false
            objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING,true);
    
            //序列化Map时对key进行排序操作,默认false
            objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS,true);
    
            //序列化char[]时以json数组输出,默认false
            objectMapper.configure(SerializationFeature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS,true);
    
            //序列化BigDecimal时是输出原始数字还是科学计数,默认false,即以toPlainString()科学计数方式来输出
            objectMapper.configure(SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN,true);

     

      下面写一个Person类,对上面介绍的序列化属性进行测试,并进行直观输出:  

     1 import com.fasterxml.jackson.annotation.JsonRootName;
     2 import org.apache.commons.lang3.StringUtils;
     3 import java.util.Date;
     4 
     5 
     6 @JsonRootName("Test")
     7 public class Person {
     8 //  @JsonInclude(JsonInclude.Include.NON_NULL)
     9   private String name;
    10 
    11   private int age;
    12 
    13   private SexEnum sex;
    14 
    15   private Date birthDay;
    16 
    17   public enum SexEnum{
    18     MAN("M", "m"),
    19     WOMAN("F", "f");
    20 
    21     private String merchantCode;
    22     private String nativeCode;
    23 
    24     SexEnum(String merchantCode, String nativeCode) {
    25       this.merchantCode = merchantCode;
    26       this.nativeCode = nativeCode;
    27     }
    28 
    29     public String getMerchantCode() {
    30       return merchantCode;
    31     }
    32 
    33     public void setMerchantCode(String merchantCode) {
    34       this.merchantCode = merchantCode;
    35     }
    36 
    37     public String getNativeCode() {
    38       return nativeCode;
    39     }
    40 
    41     public void setNativeCode(String nativeCode) {
    42       this.nativeCode = nativeCode;
    43     }
    44 
    45     @Override
    46     public String toString() {
    47       return getMerchantCode();
    48     }
    49 
    50   public Person() {
    51   }
    52 
    53   public Person(String name, int age) {
    54     this.name = name;
    55     this.age = age;
    56   }
    57 
    58   public String getName() {
    59     return name;
    60   }
    61 
    62   public void setName(String name) {
    63     this.name = name;
    64   }
    65 
    66   public int getAge() {
    67     return age;
    68   }
    69 
    70   public void setAge(int age) {
    71     this.age = age;
    72   }
    73 
    74   public SexEnum getSex() {
    75     return sex;
    76   }
    77 
    78   public void setSex(SexEnum sex) {
    79     this.sex = sex;
    80   }
    81 
    82   public Date getBirthDay() {
    83     return birthDay;
    84   }
    85 
    86   public void setBirthDay(Date birthDay) {
    87     this.birthDay = birthDay;
    88   }
    89 }
    View Code

      下面是测试类:

    1 import com.alibaba.fastjson.JSONObject;
     2 import com.example.myFirstProject.domain.Person;
     3 import com.example.myFirstProject.util.JacksonUtil;
     4 import org.joda.time.DateTime;
     5 import java.math.BigDecimal;
     6 import java.util.ArrayList;
     7 import java.util.Date;
     8 import java.util.List;
     9 import static com.example.myFirstProject.domain.Person.SexEnum;
    10 import static com.example.myFirstProject.domain.Person.SexEnum.MAN;
    11 
    12 
    13 /**
    14  * Created by bjxiaojian on 2016/10/26.
    15  */
    16 public class JacksonTest {
    17 
    18   public static void main(String[] args) {
    19 
    20     Person person = new Person();
    21 
    22     Person person1 = new Person("xiaojian", 1);
    23     person1.setSex(MAN);
    24     person1.setBirthDay(new Date());
    25     List personList = new ArrayList();
    26     personList.add(person);
    27     personList.add(person1);
    28     System.out.println(JacksonUtil.encode(person));
    29     System.out.println(JacksonUtil.encode(person1));
    30     System.out.println(JacksonUtil.encode(personList));
    31 
    32   }
    33 }
    34 
    35 
    36 ---------------------------------输出结果--------------------------------------------
    37 {"Test":{"age":0}}   null的属性不进行序列化
    38 {"Test":{"age":1,"birthDay":1477661674628,"name":"xiaojian","sex":"M"}}   date类型的输出为时间戳,枚举类的输出默认为MAN或WOMAN,设置后为SexEnum的toString()的返回值
    39 {"ArrayList":[{"age":0},{"age":1,"birthDay":1477661674628,"name":"xiaojian","sex":"M"}]}
    View Code

      3.2 反序列化属性

    1         //当遇到未知属性(没有映射到属性,没有任何setter或者任何可以处理它的handler,是否应该抛出JsonMappingException异常
     2         objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    
     3         //该特性决定对于json浮点数,是否使用BigDecimal来序列化。如果不允许,则使用Double序列化。 默认为false
     4         objectMapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, false);
    
     5         //该特性决定对于json整形(非浮点),是否使用BigInteger来序列化。如果不允许,则根据数值大小来确定 是使用Integer或者Long
     6         objectMapper.configure(DeserializationFeature.USE_BIG_INTEGER_FOR_INTS, false);
    
     7         //该特性决定JSON ARRAY是映射为Object[]还是List<Object>。如果开启,都为Object[],false时,则使用List  默认为false
     8         objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, false);
    
     9         //是否使用Enum.toString()的值对json string进行反序列化。这个的设置和WRITE_ENUMS_USING_TO_STRING需要一致。
    10         objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
    View Code

       3.3 Jackson序列化和反序列化注解 

      上面的配置是针对所有类的反序列化的设置,下面介绍针对某个类的属性和方法的反序列化的注解:

      1. @JsonIgnore:作用在字段或方法上,用来完全忽略被注解的字段和方法对应的属性。

        2.@JsonProperty:作用在字段或方法上,用来对属性的序列化/反序列化,可以用来避免遗漏属性,同时提供对属性名称重命名。

        对属性添加了@JsonProperty注解后,即使该属性为private且没有getter和setter方法,也会进行序列化。

      3.@JsonIgnoreProperties

         作用在类上,用来说明有些属性在序列化/反序列化时需要忽略掉,可以将它看做是@JsonIgnore的批量操作,它还有一个重要的功能是作用在反序列化时解析字段时过滤一些未知的属性,否则通常情况下解析到我们定义的类不认识的属性便会抛出异常。

        可以注明是想要忽略的属性列表如@JsonIgnoreProperties({"name","age","title"}),

        也可以注明过滤掉未知的属性如@JsonIgnoreProperties(ignoreUnknown=true)

      4、@JsonUnwrapped作用在属性字段或方法上,用来将子JSON对象的属性添加到封闭的JSON对象。示例如下:

    public void jsonUnwrapped() throws Exception {  
        TestPOJO testPOJO = new TestPOJO();  
        testPOJO.setId(111);  
        TestName testName = new TestName();  
        testName.setFirstName("张");  
        testName.setSecondName("三");  
        testPOJO.setName(testName);  
        ObjectMapper objectMapper = new ObjectMapper();  
        String jsonStr = objectMapper.writeValueAsString(testPOJO);  
        //如果没有@JsonUnwrapped,序列化后将为{"id":111,"name":{"firstName":"张","secondName":"三"}}  
        //因为在name属性上加了@JsonUnwrapped,所以name的子属性firstName和secondName将不会包含在name中。  
        Assert.assertEquals("{\"id\":111,\"firstName\":\"张\",\"secondName\":\"三\"}",jsonStr);  
        String jsonStr2 = "{\"id\":111,\"firstName\":\"张\",\"secondName\":\"三\"}";  
        TestPOJO testPOJO2 = objectMapper.readValue(jsonStr2,TestPOJO.class);  
        Assert.assertEquals(111,testPOJO2.getId());  
        Assert.assertEquals("张",testPOJO2.getName().getFirstName());  
        Assert.assertEquals("三",testPOJO2.getName().getSecondName());  
    }  
      
    public static class TestPOJO{  
        private int id;  
        @JsonUnwrapped  
        private TestName name;  
      
        //getters、setters省略  
    }                                                                                                                            
     public static class TestName{  
        private String firstName;  
        private String secondName;  
      
        //getters、setters省略  
    }  
    View Code

      5.@JsonSerialize和@JsonDeserialize:作用于方法和字段上,通过 using(JsonSerializer)和using(JsonDeserializer)来指定序列化和反序列化的实现。下面的例子中自定义了日期的序列化和反序列化方式,可以将Date和指定日期格式字符串之间相互转换。 

    @JsonSerialize(using = MyDateSerializer.class)  
    @JsonDeserialize(using = MyDateDeserializer.class)  
    private Date birthday; 

      6.@JsonPropertyOrder:作用在类上,被用来指明当序列化时需要对属性做排序。@jsonPropertyOrder(alphabetic = true)

      7.@JsonView:视图模板,作用于方法和属性上,用来指定哪些属性可以被包含在JSON视图中,在前面我们知道已经有@JsonIgnore和@JsonIgnoreProperties可以排除过滤掉不需要序列化的属性,可是如果一个POJO中有h很多个属性,而我们可能只需要概要简单信息即序列化时只想输出其中几个属性,此时使用@JsonIgnore和@JsonIgnoreProperties就显得非常繁琐,而使用@JsonView便会非常方便,只许在你想要输出的属性(或对应的getter)上添加@JsonView即可。

    @Test  
    public void jsonView() throws Exception {  
        TestPOJO testPOJO = new TestPOJO();  
        testPOJO.setA("1");  
        testPOJO.setB("2");  
        testPOJO.setC("3");  
        testPOJO.setD("4");  
        ObjectMapper objectMapper = new ObjectMapper();  
        objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);  
        String jsonStr = objectMapper.writerWithView(FilterView.OutputA.class).writeValueAsString(testPOJO);  
        Assert.assertEquals("{\"a\":\"1\",\"c\":\"3\"}",jsonStr);  
        String jsonStr2 = objectMapper.writerWithView(FilterView.OutputB.class).writeValueAsString(testPOJO);  
        Assert.assertEquals("{\"d\":\"4\",\"b\":\"2\"}",jsonStr2);  
    }  
      
    public static class TestPOJO{  
        @JsonView(FilterView.OutputA.class)  
        private String a;  
        @JsonView(FilterView.OutputA.class)  
        private String c;  
        @JsonView(FilterView.OutputB.class)  
        private String d;  
        @JsonView(FilterView.OutputB.class)  
        private String b;  
        //getters、setters忽略  
    }  
      
      
    private static class FilterView {  
        static class OutputA {}  
        static class OutputB {}  
    }  
    View Code

      8.@JsonFilter:Json属性过滤器,作用于类,作用同上面的@JsonView,都是过滤掉不想要的属性,输出自己想要的属性。和@FilterView不同的是@JsonFilter可以动态的过滤属性。eg:

    @Test  
    public void jsonFilter() throws Exception {  
        TestPOJO testPOJO = new TestPOJO();  
        testPOJO.setA("1");  
        testPOJO.setB("2");  
        testPOJO.setC("3");  
        testPOJO.setD("4");  
        ObjectMapper objectMapper = new ObjectMapper();  
        FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",SimpleBeanPropertyFilter.filterOutAllExcept("a"));  
        objectMapper.setFilters(filters);  
        String jsonStr = objectMapper.writeValueAsString(testPOJO);  
        Assert.assertEquals("{\"a\":\"1\"}",jsonStr);  
    }  
      
    @JsonFilter("myFilter")  
    public static class TestPOJO{  
        private String a;  
        private String c;  
        private String d;  
        private String b;  
      
        //getters、setters省略  
    }
    View Code

      定义了一个名为myFilter的SimpleFilterProvider,这个过滤器将会过滤掉所有除a属性以外的属性。

      9.@JsonAnySetter:作用于方法,在反序列化时用来处理遇到未知的属性的时候调用,在本文前面我们知道可以通过注解@JsonIgnoreProperties(ignoreUnknown=true)来过滤未知的属性,但是如果需要这些未知的属性该如何是好?那么@JsonAnySetter就可以派上用场了,它通常会和map属性配合使用用来保存未知的属性, 

    @Test  
    public void jsonAnySetter() throws Exception {  
        ObjectMapper objectMapper = new ObjectMapper();  
        String jsonStr = "{\"name\":\"myName\",\"code\":\"12345\",\"age\":12}";  
        TestPOJO testPOJO = objectMapper.readValue(jsonStr,TestPOJO.class);  
        Assert.assertEquals("myName",testPOJO.getName());  
        Assert.assertEquals("12345",testPOJO.getOther().get("code"));  
        Assert.assertEquals(12,testPOJO.getOther().get("age"));  
    }  
      
    public static class TestPOJO{  
        private String name;  
      
        private Map other = new HashMap();  
      
        @JsonAnySetter  
        public void set(String name,Object value) {  
            other.put(name,value);  
        }  
      
        //getters、setters省略  
    }  
    View Code

      3.4 Jackson序列化设置DateTime的输出格式:

      simpleModule.addSerializer(new JodaDateSerializer(DateTime.class));

      JodaDateSerializer类的代码如下:

    public class JodaDateSerializer extends StdSerializer<DateTime> {
    
        private static final Logger logger = LoggerFactory.getLogger(JodaDateSerializer.class);
    
        protected JodaDateSerializer(Class<DateTime> t) {
            super(t);
        }
    
        @Override
        public void serialize(DateTime value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
            if ( value == null ) {
                jgen.writeString("null");
            } else {
                try {
                    //DateTimeUtils是自己定义的进行DateTime和各种String格式转换的工具类
                    String str = DateTimeUtils.fmtYyyyMMddHHmmss(value);
                    jgen.writeString(str);
                } catch (Exception e) {
                    logger.error("joda serialize error: ", e);
                    jgen.writeString("unknown");
                }
    
            }
        }
    
    }
    View Code

     DateTimeUtils是自己定义的进行DateTime和各种String格式转换的工具类,代码见 第二章 DateTime工具类

     

      参考博客:http://blog.csdn.net/sdyy321/article/details/40298081#t30

     

    转载于:https://www.cnblogs.com/jian-xiao/p/6009435.html

    展开全文
  • 技术的最新进展提高了时序数据的收集、存储和分析效率,激发了人们对如何处理此类数据的考量。然而,大多数现有时序数据体系结构的处理能力,可能无法跟上时序数据的爆发性增长。作为一家根植于数据的公司,Netflix...
        

    引言

    因特网互联设备的发展,提供了大量易于访问的时序数据。越来越多的公司有兴趣去挖掘这类数据,意图从中获取一些有意义的洞悉,并据此做出决策。技术的最新进展提高了时序数据的收集、存储和分析效率,激发了人们对如何处理此类数据的考量。然而,大多数现有时序数据体系结构的处理能力,可能无法跟上时序数据的爆发性增长。

    作为一家根植于数据的公司,Netflix已习惯于面对这样的挑战,多年来一直在推进应对此类增长的解决方案。该系列博客文章分为两部分发表,我们将分享Netflix在改进时序数据存储架构上的做法,如何很好地应对数据规模的成倍增长。

    时序数据:会员视频观看记录

    每天,Netflix的全部会员会观看合计超过1.4亿小时的视频内容。观看一个视频时,每位会员会生成多个数据点,存储为视频观看记录。Netflix会分析这些视频观看数据,实时准确地记录观看书签,并为会员提供个性化推荐。具体实现可参考如下帖子:

    • 我们是如何知道会员观看视频的具体位置的?

    • 如何帮助会员在Netflix上发现值得继续观看的视频?

    视频观看的历史数据将会在以下三个维度上取得增长:

    1. 随时间的推进,每位会员会生成更多需要存储的视频观看数据。

    2. 随会员数量的增长,需要存储更多会员的视频观看数据。

    3. 随会员每月观看视频时间的增加,需要为每位会员存储更多的视频观看数据。

    Netflix经过近十年的发展,全球用户数已经超过一亿,视频观看历史数据也在大规模增长。这篇博客帖子将聚焦于其中的一个重大挑战,就是我们的团队是如何解决视频观看历史数据的规模化存储的。

    基本架构的初始设计

    640?wx_fmt=png&wxfrom=5&wx_lazy=1

    下图展示了最初使用的数据模型中的读操作和写操作流。

    640?wx_fmt=png
    图1:单表数据模型

    写操作流

    当一位会员开始播放视频时,一条观看记录会以一个新列的方式插入。当会员暂停或停止观看视频流时,观看记录会做更新。在Cassandra中,对单一列值的写操作是快速和高效的。

    读操作流

    640?wx_fmt=png

    延迟的原因

    下面介绍一些Cassandra的内部机制,进而理解为什么我们最初的简单设计会产生性能下降。随着数据的增长,SSTable的数量也随之增加。因为只有最近的数据是维护在内存中的,因此在很多情况下,检索观看历史记录时需要同时读取内存表和SSTable。这对于读取延迟具有负面影响。同样,随着数据的增长,合并(Compaction)操作将占用更多的IO和时间。此外,随着一行记录越来越宽,读修复(Read repair)和全列修复(Full column repair)也会变慢。

    缓存层

    Cassandra可以很好地对观看数据执行写操作,但是需要改进读操作上的延迟。为优化读操作延迟,我们考虑以增加写路径上的工作为代价,在Cassandra存储前增加了一个内存中的分片缓存层(即EVCache)。缓存实现为一种基本的键-值存储,键是CustomerId,值是观看历史数据的二进制压缩表示。每次Cassandra的写操作,将额外生成一次缓存查找操作。一旦缓存命中,直接给出缓存中的已有值。对于观看历史记录的读操作,首先使用缓存提供的服务。一旦缓存没有命中,再从Cassandra读取条目,压缩后插入到缓存中。

    在添加了缓存层后,多年来Cassandra单表存储方法一直工作很好。在Cassandra集群上,基于CustomerId的分区提供了很好的扩展。到2012年,查看历史记录的Cassandra集群成为了Netflix的最大专用Cassandra集群之一。为进一步实现存储的规模化,团队需要实现集群的规模翻番。这意味着,团队需要冒险进入Netflix在使用Cassandra上尚未涉足的领域。同时,Netflix业务也在持续快速增长,其中包括国际会员的增长,以及企业即将推出的自制节目业务。

    重新设计:实时存储和压缩存储

    640?wx_fmt=png

    写操作流

    对于新的观看记录,使用同上的方法写入到LiveVH。

    读操作流

    为有效地利用新设计的优点,团队更新了观看历史API,提供了读取近期数据和读取全部数据的选项。

    • 读取近期观看历史:在大多数情况下,近期观看历史仅需从LiveVH读取。这限制了数据的规模,进而给出了更低的延迟。

    • 读取完整观看历史:实现为对LiveVH和CompressVH的并行读操作。

    考虑到数据是压缩的,并且CompressedVH具有更少的列,因此读取操作涉及更少的数据,这显著地加速了读操作。

    CompressedVH更新流

    在从LiveVH读取观看历史记录时,如果记录数量超过了一个预设的阈值,那么最近观看记录将由后台任务打包(roll up)、压缩并存储在CompressedVH中。打包数据存储在一个行标识为CustomerId的新行中。新打包的数据在写入后会给出一个版本,用于读操作检查数据的一致性。只有验证了新版本的一致性后,才会删除旧版本的打包数据。出于简化的考虑,在打包中没有考虑加锁,由Cassandra负责处理非常罕见的重复写问题(即以最后写入的数据为准)。

    640?wx_fmt=png
    图2:实时数据和压缩数据的操作模型

    如图2所示,CompressedVH的打包行中还存储了元数据信息,其中包括最新版本信息、对象规模和分块信息,细节稍后介绍。记录中具有一个版本列,指向最新版本的打包数据。这样,读取CustomerId总是会返回最新打包的数据。为降低存储的压力,我们使用一个列存储打包数据。为最小化具有频繁观看模式的会员的打包频率,LiveVH中仅存储最近几天的观看历史记录。打包后,其余的记录在打包期间会与CompressedVH中的记录归并。

    通过分块实现自动扩展

    通常情况是,对于大部分的会员而言,全部的观看历史记录可存储在一行压缩数据中,这时读操作流会给出相当不错的性能。罕见情况是,对于一小部分具有大量观看历史的会员,由于最初架构中的同一问题,从一行中读取CompressedVH的性能会逐渐降低。对于这类罕见情况,我们需要对读写延迟设置一个上限,以避免对通常情况下的读写延迟产生负面影响。

    为解决这个问题,如果数据规模大于一个预先设定的阈值,我们会将打包的压缩数据切分为多个分块,并存储在不同的Cassandra节点中。即使某一会员的观看记录非常大,对分块做并行读写也会将读写延迟控制在设定的上限内。

    640?wx_fmt=png
    图3:通过数据分块实现自动扩展

    写操作流

    如图3所示,打包压缩数据基于一个预先设定的分块大小切分为多个分块。各个分块使用标识CustomerId$Version$ChunkNumber并行写入到不同的行中。在成功写入分块数据后,元数据会写入一个标识为CustomerId的单独行中。对非常大的打包观看数据,这一做法将写延迟限制为两次写操作。这时,元数据行实现为一个不具有数据列的行。这种实现支持对元数据的快速读操作。

    为加快对通常情况(即经压缩的观看数据规模小于预定的阈值)的处理,我们将元数据与观看数据合并为一行,消除查找元数据的开销,如图2所示。

    读操作流

    在读取时,首先会使用行标识CustomerId读取元数据行。对于通常情况,分块数是1,元数据行中包括了打包压缩观看数据的最新版本。对于罕见情况,存在多个压缩观看数据的分块。我们使用元数据信息(例如版本和分块数)对不同分块生成不同的行标识,并行读取所有的分块。这将读延迟限制为两次读操作。

    改进缓存层

    为了支持对大型条目的分块,我们还改进了内存中的缓存层。对于存在大量观看历史的会员,整个压缩的观看历史可能无法置于单个EVCache条目中。因此,我们采用类似于对CompressedVH模型的做法,将每个大型缓存条目分割为多个分块,并将元数据存储在首个分块中。

    结果

    在引入了并行读写、数据压缩和数据模型改进后,团队达成了如下目标:

    1. 通过数据压缩,实现了占用更少的存储空间;

    2. 通过分块和并行读写,给出了一致的读写性能;

    3. 对于通常情况,延迟限制为一次读写。对于罕见情况,延迟限制为两次读写。

    640?wx_fmt=png
    图4:运行结果

    团队实现了数据规模缩减约6倍,Cassandra维护时间降低约13倍,平均读延迟降低约5倍,平均写时间降低约1.5倍。更为重要的是,团队实现了一种可扩展的架构和存储空间,可适应Netflix观看数据的快速增长。

    公众号推荐:

    公众号:VOA英语每日一听

    微信号: voahk01

    可长按扫码关注,谢谢

    640?wx_fmt=jpeg


    展开全文
  • 针对反序列化漏洞最新的补丁修补方案如下: 针对weblogic10.3.6版本 第一步 解压p26519424_1036_Generic.zip文件到{MW_HOME}/util/bsu/cache_dir如果没有cache_dir文件夹则新建即可。第二步(如果没有打过ZLNA、...

    针对反序列化漏洞最新的补丁修补方案如下: 
    针对weblogic10.3.6版本 
    第一步 
    解压p26519424_1036_Generic.zip文件到{MW_HOME}/util/bsu/cache_dir如果没有cache_dir文件夹则新建即可。

    第二步(如果没有打过ZLNA、EJUW两个补丁的,此步骤可略过) 

    使用如下命令查看是否打过ZLNA和EJUW补丁包:

    ./bsu.sh  -prod_dir=/home/weblogic/Oracle/Middleware/wlserver_10.3/ -status=applied -verbose –view

    如果有则运行如下命令删除ZLNA和EJUW补丁包

    1、./bsu.sh -remove -patchlist=ZLNA -prod_dir=/home/weblogic/Oracle/Middleware/wlserver_10.3 
    2、./bsu.sh -remove -patchlist=EJUW -prod_dir=/home/weblogic/Oracle/Middleware/wlserver_10.3 
    备注:FMJJ与ZLNA、EJUW冲突,必须先移除ZLNA,再移除EJUW(是ZLNA的升级包)

    第三步 安装最新版本的weblogic反序列化补丁包FMJJ
    ./bsu.sh  -install  -patch_download_dir=/home/weblogic/Oracle/Middleware/utils/bsu/cache_dir  -patchlist=FMJJ  -prod_dir=/home/weblogic/Oracle/Middleware/wlserver_10.3/

    图片步骤: 
    这里写图片描述

    这里写图片描述

    运行:

    ./bsu.sh  -prod_dir=/home/weblogic/Oracle/Middleware/wlserver_10.3/ -status=applied -verbose –view


    则weblogic反序列化最新补丁包安装完成。

    展开全文
  • C++ 序列化库 Cereal使用()

    千次阅读 2019-11-05 20:29:10
    Cereal 是个head only开源的C++11序列化库,支持自定义数据类型序列化成JSON,XML,二进制压缩,反之也可以反序列化。几乎不依赖于其他三方库(RapidJson,RadidXml),方便快速。 下载 由于是开源项目,直接在Github...

    cereal 介绍

    Cereal 是一个head only开源的C++11序列化库,支持自定义数据类型序列化成JSON,XML,二进制压缩,反之也可以反序列化。几乎不依赖于其他第三方库(RapidJson,RadidXml),方便快速。

    下载

    由于是开源项目,直接在Github上可以下载最新版本.

    github

    git clone git@github.com:USCiLab/cereal.git
    
    

    使用

    配置

    将上一步下载下来的库包含到自己的工程路径中来,比如:

    INCLUDEPATH +=$$PWD/Cereal
    

    定义数据类型

    定义自己的数据类型,编写序列化函数,以下是我自己代码中测试的类:

    class QDicomTag
    {
    public:
        QDicomTag();
        ~QDicomTag();
    
        /*! 自定义序列化函数*/
        template <class Archive>
        friend void serialize( Archive & ar, const QDicomTag &tag, std::uint32_t const &version);
    
    public:
        void cleanTag();
    
        bool loadTag(DcmDataset *pDataSet);
        bool loadTagGroup0008(DcmDataset *pDataSet);
        bool loadTagGroup0010(DcmDataset *pDataSet);
        bool loadTagGroup0020(DcmDataset *pDataSet);
        bool loadTagGroup0028(DcmDataset *pDataSet);
    
        std::string m_strImageType;                         // (0008,0008)
        std::string m_strSopClassUID;                       // (0008,0016)
        std::string m_strSopInstanceUID;                    // (0008,0018)
        std::string m_strStudyDate;                         // (0008,0020)
        std::string m_strSeriesDate;                        // (0008,0021)
    };
    
    template<class Archive>
    void serialize(Archive &ar, const QDicomTag &tag, std::uint32_t const &version)
    {
        (void)version;
    
        ar(cereal::make_nvp("imageType", tag.m_strImageType)
           ,cereal::make_nvp("sopClassUID", tag.m_strSopClassUID)
           ,cereal::make_nvp("sopInstanceUID", tag.m_strSopInstanceUID)
           );
    }
    
    

    关键部分是编写序列化函数,具体序列化由序列化函数来实现,我这里为了代码整洁,序列化函数放在了类的外部,具体可以看后面的序列化函数.

    开始序列化

    需要包含头文件

    #include "cereal/macros.hpp"
    #include "cereal/specialize.hpp"
    #include "cereal/version.hpp"
    #include "cereal/access.hpp"
    #include "cereal/cereal.hpp"
    
    #include "cereal/archives/binary.hpp"
    #include "cereal/archives/xml.hpp"
    #include "cereal/archives/json.hpp"
    
    #include "cereal/types/memory.hpp"
    #include "cereal/types/string.hpp"
    #include <cereal/types/vector.hpp>
    #include <cereal/types/complex.hpp>
    #include <cereal/types/map.hpp>
    
    {
    	QString strFile = "D:/dev/TestSerialization.json";
        std::ofstream os(strFile.toStdString ());
        cereal::JSONOutputArchive archive(os);
    
        QDicomTag tag;
        // ....这里省去tag结构的初始化工作
    
        archive(cereal::make_nvp("dicomTag" ,tag));	
    }
    

    序列化函数

    序列化函数可以分为以下几种,具体类的结构如上面定义的DicomTag

    定义在类的内部

    1. 使用单个序列化函数
    template<class Archive>
    void serialize(Archive &ar)
    {
    	ar(m_strImageType, m_strSopClassUID, m_strStudyDate, m_strSeriesDate);
    }
    

    可以根据自己需要,选择序列化的字段,序列化函数中列出的项均会被序列化,上面的写法,在序列化输出后会自动添加Value0.....字段值,为了方便可以添加自己的字段名:

    template<class Archive>
    void serialize(Archive &ar)
    {
    	    ar(cereal::make_nvp("imageType", tag.m_strImageType)
           ,cereal::make_nvp("sopClassUID", tag.m_strSopClassUID)
           ,cereal::make_nvp("sopInstanceUID", tag.m_strSopInstanceUID)
           );
    }
    

    具体输出结果

    • XML
    <?xml version="1.0" encoding="utf-8"?>
    <cereal>
    	<dicomTag>
    		<imageType>DERIVED</imageType>
    		<sopClassUID>1.2.840.10008.5.1.4.1.1.7</sopClassUID>
    		<sopInstanceUID>1.2.156.14702.1.1005.128.2.201607141416245011010000001</sopInstanceUID>
    	</dicomTag>
    </cereal>
    
    • JSON
    {
        "dicomTag": {
            "imageType": "DERIVED",
            "sopClassUID": "1.2.840.10008.5.1.4.1.1.7",
            "sopInstanceUID": "1.2.156.14702.1.1005.128.2.201607141416245011010000001",
        }
    }
    
    1. 分来save和load函数
    template<class Archive>
    void save(Archive &ar) const
    {
    		ar(cereal::make_nvp("imageType", tag.m_strImageType)
           ,cereal::make_nvp("sopClassUID", tag.m_strSopClassUID)
           ,cereal::make_nvp("sopInstanceUID", tag.m_strSopInstanceUID)
           );
    }
    
    template<class Archive>
    void load(Archive &ar) const
    {
    		ar(cereal::make_nvp("imageType", tag.m_strImageType)
           ,cereal::make_nvp("sopClassUID", tag.m_strSopClassUID)
           ,cereal::make_nvp("sopInstanceUID", tag.m_strSopInstanceUID)
           );
    }
    

    上述函数,输出后结果和1相同.

    定义在类的外部

    1. 使用单个序列化函数
    class QDicomTag
    {
    public:
        QDicomTag();
        ~QDicomTag();
    
        /*! 自定义序列化函数*/
        template <class Archive>
        friend void serialize( Archive & ar, const QDicomTag &tag, std::uint32_t const &version);
    };
    
    template<class Archive>
    void serialize(Archive &ar, const QDicomTag &tag, std::uint32_t const &version)
    {
        (void)version;
    
        ar(cereal::make_nvp("imageType", tag.m_strImageType)
           ,cereal::make_nvp("sopClassUID", tag.m_strSopClassUID)
           ,cereal::make_nvp("sopInstanceUID", tag.m_strSopInstanceUID)
           );
    }
    
    
    1. 分来save和load函数
    class QDicomTag
    {
    public:
        QDicomTag();
        ~QDicomTag();
    
        /*! 自定义序列化函数*/
        template <class Archive>
        friend void save(Archive &a, const QDicomTag &tag, std::uint32_t const &version);
    
        template <class Archive>
        friend void load(Archive &a, const QDicomTag &tag, std::uint32_t const &version);
    };
    
    template<class Archive>
    void save(Archive &ar, const QDicomTag &tag, std::uint32_t const &version)
    {
        (void)version;
    
        ar(cereal::make_nvp("imageType", tag.m_strImageType)
           ,cereal::make_nvp("sopClassUID", tag.m_strSopClassUID)
           ,cereal::make_nvp("sopInstanceUID", tag.m_strSopInstanceUID)
           );
    }
    
    template<class Archive>
    void load(Archive &ar, const QDicomTag &tag, std::uint32_t const &version)
    {
        (void)version;
    
        ar(cereal::make_nvp("imageType", tag.m_strImageType)
           ,cereal::make_nvp("sopClassUID", tag.m_strSopClassUID)
           ,cereal::make_nvp("sopInstanceUID", tag.m_strSopInstanceUID)
           );
    }
    
    

    其他

    参考文章

    • [cereal官方文档] 1

    作者:鹅卵石
    时间: 2019年11月2日22:33:08
    版本:V 0.0.1
    邮箱:kevinlq@163.com
    微信公众号:devstone
    版权:本博客若无特别声明,均属于作者原创文章,欢迎大家转载分享。但是,
    希望您注明来源,并留下原文地址,这是对作者最大的尊重,也是对知识的尊重。
    

    如果您对本文有任何问题,可以在下方留言,或者Email我.

    关注我


    展开全文
  • 我发现分享的数据都是80k那种部分的。先现在上传 最新版本的,800k完整版
  • 我们专注于神经机器翻译(NMT)的任务,这是带有wild的seq2seq模型的第一个测试平台。 所包含的代码轻巧,高质量,可立即投入生产,并结合了最新的研究思路。 我们通过以下方式实现这一目标: 使用最新的解码器/注意...
  • 洛谷P1631 序列合并

    2016-09-05 20:53:00
    P1631 序列合并 236通过 657提交 题目提供者xmyzwls ...最新讨论 ...有两个长度都是N的序列A和B,在A和B中各取一个数相加可以得到N^2个和,求这N^2个和中最小的N个。...第一行一个正整数N; 第二行N个整数Ai,满足...
  • Solidity教程序列1 - 类型介绍

    千次阅读 2017-12-07 09:32:56
    Solidity语法的介绍会是一系列文章,本文是第一篇:介绍Solidity的变量类型。本文前半部分是参考Solidity官方文档(当前最新版本:0.4.20)进行翻译,前半部分是实际合约代码实例说明类型的使用。类型Solidi
  • ner,命名实体识别是关系抽取中非常重要的一个任务。...首先第一步是处理数据 我们首先在github上找到一个数据汇总的repo,下载下来或者git clone下来都可以。https://github.com/InsaneLife/ChineseNLPCorpus/tre...
  • C Primer Plus 六版 编程练习八章答案 最新出炉提示1.设计个程序, 统计在读到文件结尾之前读取的字符数。2.编写个程序, 在遇到 EOF 之前, 把输入作为字符流读取。 程序要打印每个输入的字符及其相应的...
  • 第一行一个正整数n,代表序列长度 第二行n个空格隔开的数,代表序列 Output 输出该序列段数 解题思路 以当前的数为段的标识数,依次遍历,相同的过,不同的则说明不在一个段内,ans+1,并以最新的数作为新段的标识,...
  • Bengio团队最新的Paper,将纯深度学习技术应用于时间序列预测,并在测试数据集上取得了比传统时间充列分析还要好的效果,他们分别发表了两篇文章,第一篇发表于19年5月,讲述了N-BEATS算法,第二篇发表于20年2月,将...
  • 第一个Thrift程序

    2019-08-25 18:29:57
    Thrift是个rpc框架,也是个不错的序列化框架,支持多种语言,此处我使用的是Java。 1、当然开始之前需要下载thrift到本地,我这里下载的是最新的0.12.0版本,并设置好环境变量 2、编写IDL ##命令空间 ...
  • 我们专注于神经机器翻译(NMT)的任务,这是带有wild的seq2seq模型的第一个测试平台。 所包含的代码轻巧,高质量,可立即投入生产,并结合了最新的研究思路。 我们通过以下方式实现这一目标: 使用最新的解码器/注意...
  • 对计量经济学和统计学文献中的金融计量方法的最新进展进行概述是本书的 突出特点,这些进展包括当前的研究热点,如风险值、高频数据分析和马尔可夫链蒙特卡罗方法等。 强调实例和数据分析是本书的另个突出特点、...
  • 第一个原理开始,汉密尔顿的明析介绍使得新旧进展皆适合于大学一年级学生和非专业人员。另外,时间序列分析从内容的广度和深度上使其成为该领域前沿研究者不可多得的一本参考书。汉密尔顿通过大量的数值例子解释...
  • 习题三参考答案 备注 : 红色字体标明的是与书本内容有改动的内容 选择题 1. 在栈中存取数据的原则是 B A 先进先出 B. 先进后出 C. 后进后出 D. 没有限制 2 若将整数 12 3 4 依次进栈则不可能得到的出栈序列是 D A ...
  • hydra-java, 注释你的javabean并将它们序列化为hydra的json java 注释你的javabean并将它们序列化为 json,与 hydra 。状态:测试。...最新版本:0.3.1目录问题解决方案( 正在进化)第一步。spring的
  • 第一步,我们需要收集一些数据:在本示例中,我们将使用提及AMZN标记符号的大量推文。 import pandas as pd url = ...
  • TimeBox是个过程库,它实现用于评估时间序列分类方法的数据结构和功能。 除此软件中包含的三方材料外,TimeBox均根据Apache许可版本2.0(“许可”)获得许可; 除非遵守许可,否则您不得使用TimeBox。 您可以在...
  • 2. 先开始操作X(A 或 B),再进行个合法操作序列,最后结束操作X,这样个操作序列个合法操作序列 3. 把合法操作序列X和Y连起来,也是个合法操作序列 如: - (), [], (()), ()[()], (()()) 都是合...
  • 但是,如果在此时间段内上传新图片,则第一页的最后一张图片将成为第二页的第一项。 为了防止这个问题,可以使用许多替代方法。 最好的选择之一是使用时间戳而不是页码。 这个分页器根据项目的时间戳进行分页。 ...
  • CUDAlign是种工具,可以使用Smith-Waterman算法与Myers-Miller结合使用,在CUDA GPU中比对大小不受限制的成对DNA序列。 使用GTX 560 Ti,可以在45秒内产生100万个碱基序列的最佳比对。 正在为此软件开发许多优化。...
  • 论文研究-建立系统科学基础理论框架的种可能途径与若干具体思路(之七)——离散动力系统的密度演化与序列的信息结构.pdf, 本文是总题目下的七篇。全文的总目的是试图...
  • 思路:强制在线,保存每个线性基的数值,接下去直接去搜r个线性基,但要保持时间比l要大,新增了个pos数组代表个数插入时的时间戳,插入的时候如果可以替换那么就用之后的替换之前的,保证线性基中都是最新的...
  • 刚换工作,BOSS让将公司原来的VC6程序移植到VS2010上,前面很多移植都还算很顺利,后来到序列化这块儿,老是出错,我就纳了闷了,程序读取文件信息时,序列化那个类的第一个对象时一切正常,序列化该类的第二个对象...
  • 该模型的新颖之处在于,它仅使用最后个输入作为变压器编码器中的查询,而不是所有序列,这使得变压器编码器中的QK矩阵乘法具有O(L)时间复杂度,而不是O(L ^ 2) 。 它允许模型输入更长的序列。 模型架构 用法 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 578
精华内容 231
关键字:

最新第一序列