`
snake1987
  • 浏览: 72729 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

近月学习记录(一)

    博客分类:
  • java
阅读更多
最近换了一个公司,确切来说应该是进入了一个新的行业,很多东西的学习都是从0开始的,学的东西很多很杂,先分点记下,以便以后复习回忆或者近一步学习

1.key-value数据库
像redis,memcached都是这样的数据库,网上有一篇小日本的文章,写得很详细很好,虽然是小日本的,但也只能将就一下了
memcached全面剖析系列
再说一下学习中了解到它的一些特点(可能有些不准确的地方):
1.它像一个大map,所有的内容都是键值对
2.它的所有内容都是放内存中的,但可以用其他的辅助手段做持久化
3.因为是操作内存的,而且只有纯粹的操作,没有任何额外的过程(像sql的编译),所以它很快,快得难以想象,但这个快是以牺牲很多其他的东西为代价的
4.它难以维护,它没有图形化操作工具,这也很容易理解,像我们想去像维护sql数据库一样维护一个map,你能有什么好办法吗?
5.没有数据完整性之类的概念,所有逻辑上的关联都是人为地去维护的,所以让它更进一步难以维护。
6.因为它的所有数据都放在内存中的,所以数据库服务器崩溃对数据的影响几乎是致命的(即使你使用了一些持久化的办法)
7.它也算个新生的东西,所以很多东西很不完善,像memcached的协议还是只有文本形式的,二进制协议正在制定中。
8.memcached集群默认中的一致性hash的用的是一个圆圈形的连续的hash值,服务器对应的hash值一般是不连续的,动态增减服务器会变得很方便。具体可以看小日本的文章
9.数据库服务器的主要硬件消耗是内存,而非cpu,小日本的文章也说了,cpu使用率几乎为0
10.它与sql数据库的区别也是很明显的,它更注重的是简单而高效。

近日用这种数据库进行了一些开发,也获得了一些经验和收获
1.虽然数据库没有提供主键外键这样一些的关联,但事实上是需要的,这时我们会人为的去维护这样一个关系,如存入一个对象,对象中带着一个list,这个list中可以索引到另外的一些key值,我们人为地使用一些原子操作去维护他们之前的关系(可以看到它的不稳健性),实质上是将数据库的一些工作由我们人为地去维护了。
2.在分布式的架构中,对整个应用的同步操作可以通过数据库来做,在思考模式上,与传统的单机上的并发是完全不一样的。
举个例子:
for(;;)
{
int expect = atomicInteger.get();
if(atomicInteger.cas(expect,expect+1))
break;
}

像我们经常使用的一个cas操作,在分布式的同步中,是不推荐的,因为对于单机,get,cas都是对内存(或者说是对cpu)的一个操作,效率是很高效,但对于远程数据库而言,他就是2个远程访问了,上述的一个操作是会大大增加io的压力的(尤其是冲突域相对较大,对这个原子变量的修改频繁的情况更是明显)。
所以在分布式的同步中,能用append,add这样的原子操作会更好
另一点是精确模型和不精确模型(现在只是有一些感觉,其实理解还是不深刻,之后需要找点书来学习一下),举个例子,对于key-value数据库,我们存了一个整形列表,列表里面的内容是我们需要的一些数据,如果是需求精确模型的,我们需要用cas进行插入或者删除操作,如果是不精确模型,我们可能只是进行append,而不去计较是否重复等,某个时候做一个整体判断,然后set
如果不是需求很明确地要求精确,不精确模型会大大减轻数据库的压力(这也让我对之前学习并发的时候的一些想法发生了巨大的改变,因为在实际应用中,不是都必须要求绝对准确的,像incre,某些时候,我们不要求它一定会增加了1,甚至减少我们也是允许的)
3.memcached的cas用的是乐观锁,也就是通过一个版本号来进行的
4.锁操作可以通过一个add或者remove,cas来进行,但像锁的await和notify动作就无法实现了,只能通过客户端的轮训来做,这个锁的值如果是一个时间戳会有很多好处,如某个锁操作进行了,但没有释放服务器就崩溃了,我们这时可以判断这个时间戳到当前时间的时间差,如果远远超过了可能锁住的时间,我们就帮他解锁

2.protobuf
公司用了protobuf,在日常工作中都有所接触,一直没有时间做一些深入一点的探究,今天忙中偷闲,深入理解了一下,以下是个人的一些的总结,如果有遗漏或者错误的地方,还请看到的tx斧正

2.1.protobuf的功能
protobuf是一个google开发的开源工具,作用正如主页上说的:serialize and retrieve structured data
说白了,其实它的功能跟java的序列化和反序列化是一样的,只不过更强大,更有效率
但是在日常使用中,还会遇到这样几个问题:
a.数据结构的增删改查对之前的数据的是否会有影响,也就是版本兼容性
b.数据的压缩比率
c.易用性
d.性能
下文主要就逐步围绕这几方面进行进一步的探究

2.2.怎么用protobuf?(简单提一下)
a.按照说明编写一个.proto文件
b.用google提供的编译工具进行编译
这样,一个专负责序列化和反序列化的类就生成了,然后你可以直接去调用这个类进行序列化和反序列化了

2.3.protobuf支持的数据类型和编码

其实有用的也就4种,变长的,int32,int64和长度不限制“Length-delimited”
对于java来说,一般用的也就8种数据类型而已

下面开始对java的每种数据类型进行进一步的分析(为了方便懒得看google文档的tx,这里也稍微翻译一下)
稍微写了段测试代码
public class Student {

    public static void main(String[] args) {
        StudentProtoBuf.Student.Builder studentProtoBuf = StudentProtoBuf.Student.newBuilder();
        //studentProtoBuf.setId(1111);
        //studentProtoBuf.setName("test");
        studentProtoBuf.setSex(true);
        byte[] bytes = studentProtoBuf.build().toByteArray();
        StringBuilder builder = new StringBuilder();
        for(byte b : bytes) {
            builder.append(parseToString(b));
            builder.append(":");
        }
        System.out.println(builder.toString());
    }

    public static String parseToString(byte b) {
        int result = b & 0xff;
        String resutString = Integer.toHexString(result);
        return resutString.length() == 1 ? "0" + resutString : resutString;
    }


}

下面是proto文件的内容,上面的java代码引用的是编译后的代码
package tutorial;

option java_package = "com.hoolai.protobuf.test";
option java_outer_classname = "StudentProtoBuf";

message Student {
  optional string name = 1;
  optional int64 id = 2;
  optional bool sex = 3;

}

根据文档所说的,varint的编码规则是(field_number << 3) | wire_type,
而value部分的编码则是用的是很多协议都一样的:首bit表示后面是否还有内容,后7位才是有效位
单单一个bool,输出结果是18:01,0001 1000 0000 0001,
field_number = 3,wire_type = 0,第一个byte就出来了,然后是第二个,没什么问题
一个long+一个bool,输出是10:d7:08:18:01
可以看到编码是相邻着的,没有任何的间隔,而根据协议,在解码时也可以很简单地还原为各数据类型的有效数据(即使没有.proto编译出来的文件,也就是说使用抓包工具进行直接报文分析是可以的,如果有时间,再练练手去,但到底有没有价值呢?还待商榷)

然后进一步往后推,protobuf在做版本兼容的时候,会怎么做呢?
增:增加的时候,只有读之前的数据需要处理,如果我自己来实现,先是将整个报文进行分析,解码成具体类型的一个个值,还有他们的序号,然后对号入座,发现没有的,就给他一个默认值,很简单
删:这也很简单,也就是发现不需要的,直接丢弃就ok了,而之前的数据也不会占空间,因为当我们读取后再次存取的时候,这些数据也同时清空了,唯一只有个要求:该索引不能重用
改:改其实相当于增跟删的结合,举个例子:一个数据一开始是int,现在需要改成long,但数据需要保留,
很简单,在.proto中删除旧的int,加入新的long(注意,索引不能重用),读的时候还是按正常,当拿到解码后的数据,先看一下原索引的值是否为空,不为空,则读取并放入新的数据类型中,存的时候则按正常的逻辑就可以了,这样,.proto中的东西就可以删掉了

当然,以上的东西都是猜的,google应该也是这样做的吧?
在api中找到了这样的api:getUnknownFields().getField(4).getVarintList();
有点像了,再试试
看代码
byte[] result = {0x0a,0x04,0x74,0x65,0x73,0x74,0x10,(byte) 0xd7,0x08,0x18,0x01,0x20,0x01};//之前的代码System.out出来的,后面加了,0x20,0x01,意思是序号为第四的,用varint编码,并且值为1
        com.hoolai.protobuf.test.StudentProtoBuf.Student student = StudentProtoBuf.Student.parseFrom(result);
        student.getUnknownFields().getField(4).getVarintList();
        System.out.println(student);

果然拿到了没定义的数据

根据编码规则,很容易看出该协议的压缩算法只是到byte级的,也没有long,int,short之类的概念,对于bool这样的,就有点浪费了(之后再看看package是怎么编码的)
而对于int,short之类的,压缩比率也不大(起码没预料中的高效,因为一直认为谷歌是神一样的存在),值在0-127之前的,才是2个byte(一个作为索引和类型,一个存储值),再往上加,就需要更多的空间了,除了头个byte之外,后面的byte利用率也只有7/8,跟之前练手做的snmp协议是一样的

接下来是package了,对单个参数无所谓,但对于数组这样的,总可以优化吧
继续测试
package tutorial;

option java_package = "com.hoolai.protobuf.test";
option java_outer_classname = "StudentProtoBuf";

message Student {
  repeated bool sex = 1 [packed=true];
  repeated int32 id = 2 [packed=true];
}

    public static void main(String[] args) throws InvalidProtocolBufferException {
        StudentProtoBuf.Student.Builder studentProtoBuf = StudentProtoBuf.Student.newBuilder();
        studentProtoBuf.addSex(true);
        studentProtoBuf.addSex(false);
        studentProtoBuf.addSex(false);
        studentProtoBuf.addSex(true);
        byte[] bytes = studentProtoBuf.build().toByteArray();
        StringBuilder builder = new StringBuilder();
        for(byte b : bytes) {
            builder.append(parseToString(b));
            builder.append(":");
        }
        System.out.println(builder.toString());
    }

    public static String parseToString(byte b) {
        int result = b & 0xff;
        String resutString = Integer.toHexString(result);
        return resutString.length() == 1 ? "0" + resutString : resutString;
    }


很失望~真的没做压缩,只是按照文档所说的,当成了“Length-delimited”,然后再进行编码,结果如下:
0a:04:01:00:00:01

把package去掉看看?
08:01:08:00:08:00:08:01

完全按单个的形式来编码的~~



至此,protobuf已基本明晰了,包括一些细节,如
enum:按varint编码
repeat非package:当成“Length-delimited”,再按varint进行编码
只是repeat:按正常编码,然后用同一个索引

总的来说,对文档的解读算是全部明晰了,但对google的神话也有点失望

再看看易用性

protobuf生成的类其实就是一个DTO,因为它是由编译生成的,所以为了以后扩展方便,我们不能修改它,这样想使用它就有两种方式(如果你之前设计中没有DTO的概念),一种是继承它(缺点是代码后期会稍微有点乱),一种是做一次拷贝(条理较为清晰,但效率上显然会稍慢,毕竟多一次对象拷贝的过程)
如果本身就有DTO,那就简单了,只需要替换DTO就ok了



3.java与c的对接
1.c的char是一个byte的,但java的是两个
2.c中对多个byte的数据类型的编码会根据环境的不同而不同,java则默认就是网络序,而网络序就是我们正常的读取习惯(这个序特别容易搞乱,尤其是自己code的时候,建议写单元测试用ByteBuffer进行验证一下)

  • 大小: 31.9 KB
分享到:
评论

相关推荐

    《Java JDK6学习笔记》

    近些日学习一下ruby方面的,顺便看看java方面的, 这个是Java JDK6的学习笔记电子版, 压缩包里包含两个文件, 一个是chm格式(这个还行吧),当然如果你喜欢PDF,你可使用ABC Amber CHM Converter转换一下就可以了,...

    机器学习学习笔记

    整理者黄海广对课程笔记的更新和维护付出了巨大的努力,从2014年12月至今,课程文档经过了多次修改和更新,内容从最初的介绍到加入了线性代数的复习,再到之后的多变量线性回归等内容,体现了对机器学习课程内容的...

    sketchup8.0学习笔记

    Sketchup 8.0是一个功能强大且灵活的3D模型设计软件,本笔记记录了Sketchup 8.0的基础操作和技巧,旨在帮助初学者快速掌握Sketchup 8.0的使用。 视图操作: 1. 环绕观察:点击环绕观察按钮,可以观察模型。小技巧...

    SATA学习笔记

    SATA学习笔记 SATA(Serial Advanced Technology Attachment)是一种高速串行接口技术,用于连接计算机和存储设备,如硬盘、固态硬盘、U盘等。下面是SATA学习笔记的详细知识点: 硬盘基本概念 硬盘是计算机系统的...

    《深度学习进阶-自然语言处理》-【日】斋藤康毅著。个人学习整理简单笔记,欢迎一起学习探讨, 小白一枚,希望寻找小伙伴.zip

    由于提供的压缩包文件列表只有一个文件名"ahao2",无法确定具体笔记内容,以上都是基于书名和描述的常规NLP学习路径。实际笔记可能包含这些主题的详细解析、代码示例和实践经验,对于初学者来说是非常宝贵的参考资料...

    C#6.0学习笔记——从第一行C#代码到第一个项目设计(第二个包)

    为提高读者学习效率,本书提供了21章的配书视频教程及近300个实例的源代码。这些宝贵的学习资源有助于读者迅速入门,动手开发实践。 本书既适合作为C#完全自学图书,也适合作为相关培训机构的培训教材或者高校...

    python机器学习笔记.zip

    本人近半年自学python 方面全套的学习笔记。人生苦短,我用python。包含web、前端、django、flask、机器学习、深度学习、数据分析,还有常用如mysql、redis数据库相关材料

    C#6.0学习笔记——从第一行C#代码到第一个项目设计(第一个包)

    为提高读者学习效率,本书提供了21章的配书视频教程及近300个实例的源代码。这些宝贵的学习资源有助于读者迅速入门,动手开发实践。 本书既适合作为C#完全自学图书,也适合作为相关培训机构的培训教材或者高校...

    软考中级网工考试学习笔记

    1、包括网工第五版较全面的学习笔记(近4万字)、常用检测命令实践图、协议神图、常见编码图、网工简单的100条知识点 2、笔记目录如: 第一章 计算机基础知识 一、数据表示 (一) 定点和浮点和整数 二、逻辑计算机 ...

    机器学习实战学习笔记.zip

    自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...

    一年级语文下册培优补差记录表.pdf

    本资源是关于一年级语文下册的“培优补差”记录表,旨在帮助学生弥补语文学习中的差距,并提高语文能力。该记录表涵盖了多个方面的内容,包括汉字的笔画数、形近字的辨析、汉字结构、部首和偏旁、查字典方法等。 ...

    大数据技术原理学习笔记.docx

    本笔记基于林子雨老师在MOOC上的《大数据技术原理》课程,旨在为IT从业者和大学生提供一个全面了解大数据的基础框架。 首先,我们要认识到大数据的发展背景。随着互联网的普及,以及物联网、社交媒体、移动设备等...

    机器学习、深度学习笔记.zip

    自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...

    《机器学习实战》学习笔记.zip

    自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...

    数据结构与算法学习笔记.docx

    数据结构与算法学习笔记 本文档概括了数据结构和算法...本文档为读者提供了一个系统的数据结构和算法学习笔记,涵盖了堆、线索化二叉树、赫夫曼树等重要概念。读者可以通过学习本文档来掌握这些重要的数据结构和算法。

    《机器学习实战》学习笔记。.zip

    自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...

    机器学习笔记.zip

    自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...

    机器学习实战学习记录.zip

    自20世纪80年代以来,机器学习作为实现人工智能的途径,在人工智能界引起了广泛的兴趣,特别是近十几年来,机器学习领域的研究工作发展很快,它已成为人工智能的重要课题之一。机器学习不仅在基于知识的系统中得到...

Global site tag (gtag.js) - Google Analytics