精华内容
下载资源
问答
  • 2021-08-25 21:00:05

    基础架构

    在这里插入图片描述
    多主架构:大多数分布式系统如 HDFS、Spark、HBase 和 Elasticsearch,采用的都是 Master-Slave 主从架构,由一个管控节点作为 Leader,其它节点为 Slave。而 CH 则采用 Multi-Master 多主架构,集群中的每个节点角色相同,客户端访问任意一个节点都能得到同样的效果。这种架构因角色相同使系统架构变得更加简单,不用再区分主控节点、数据节点和计算节点,集群中的所有节点功能相同,所以就不存在单点故障问题了。
    ClickHouse 既可以单机运行,又可以分布式运行。
    在单机情况下,可以在一个服务器上运行一个 ClickHouse 进程,在分布式情况下,ClickHouse 分为多个 Shard,Shard 和 Shard 之间的数据是完全隔离的,在数据分配上可以通过 random 的 Shard,或者是 hash 方式的 Shard 去分配数据所去的 Shard。每个 Shard 内部可以有多个副本(主机 + 从机 = 副本),每个 Shard 中的 ClickHouse 互为副本,副本与副本之间的数据是完全一致的,作用就是保证集群的高可用,每一个 Shard 中的副本数是可以随意拓展的,也就是 Shard 与 Shard 之间的副本数可以不一致,假如业务上有些查询热点情况在 Shard0 上,那么 Shard0 的压力会非常大,那么可以为 Shard0 指定更多的副本数,从而缓解 Shard0 上查询热点的压力,但是在拓展时,新加入的副本无法自动进行数据的同步,这是一个不足。

    部署

    基础安装

    下载安装包
    https://packagecloud.io/altinity/clickhouse 路径下下载对应系统版本的安装包

    wget --content-disposition https://packagecloud.io/Altinity/clickhouse/packages/el/7/clickhouse-test-20.8.20.1-1.el7.x86_64.rpm/download.rpm
    wget --content-disposition https://packagecloud.io/Altinity/clickhouse/packages/el/7/clickhouse-server-common-20.8.20.1-1.el7.x86_64.rpm/download.rpm
    wget --content-disposition https://packagecloud.io/Altinity/clickhouse/packages/el/7/clickhouse-server-20.8.20.1-1.el7.x86_64.rpm/download.rpm
    wget --content-disposition https://packagecloud.io/Altinity/clickhouse/packages/el/7/clickhouse-common-static-20.8.20.1-1.el7.x86_64.rpm/download.rpm
    wget --content-disposition https://packagecloud.io/Altinity/clickhouse/packages/el/7/clickhouse-client-20.8.20.1-1.el7.x86_64.rpm/download.rpm
    rpm -ivh clickhouse-common-static-20.8.20.1-1.el7.x86_64.rpm 
    rpm -ivh clickhouse-server-common-20.8.20.1-1.el7.x86_64.rpm 
    rpm -ivh clickhouse-server-20.8.20.1-1.el7.x86_64.rpm 
    rpm -ivh clickhouse-client-20.8.20.1-1.el7.x86_64.rpm
    

    rpm安装完毕无误后,clickhouse-server和clickhouse-client配置目录如下

    [root@ck01 clickhouse]# ll /etc/clickhouse-server/
    -rw-r--r-- 1 root root 34331 824 23:56 config.xml
    -rw-r--r-- 1 root root  5587 824 23:56 users.xml
    [root@ck01 clickhouse]# ll /etc/clickhouse-server/
    -rw-r--r-- 1 root root 34331 824 23:56 config.xml
    -rw-r--r-- 1 root root  5587 824 23:56 users.xml
    
    vim /etc/clickhouse-server/config.xml
    监听ip修改
    <listen_host>0.0.0.0</listen_host>
    
    <!-- Path to data directory, with trailing slash. -->
    <path>/home/clickhouse/data/clickhouse</path>
    

    日志路径,数据路径可以适当进行修改,新路径需要改用户、用户组
    注意这个配置的目录磁盘空间必须足够大
    其他配置可以根据自己的实际情况而定,注意配置端口是否被占用


    如果路径修改了,必须预先创建对应的文件夹,不然启动会报错:UNKNOWN

    chown -R clickhouse:clickhouse clickhouse/
    

    单机版

    单机版不需要zookeeper

    启动clickhouse-server

    $: /etc/init.d/clickhouse-server start
    

    停止clickhouse-server:

    $: /etc/init.d/clickhouse-server stop
    

    进入clickhouse-client:

    $: clickhouse-client --host 127.0.0.1 --port 9000
    

    通过查询验证客户端成功 :select 1
    在这里插入图片描述

    集群部署

    zookeeper额外部署,这边就不演示zookeeper部署了

    配置修改

    vim /etc/metrika.xml,添加配置信息如下:

    <yandex>
        <clickhouse_remote_servers>
            <my_cluster>
                <shard>
                    <internal_replication>true</internal_replication>
                    <replica>
                        <host>172.17.2.143</host>
                        <port>9000</port>
                    </replica>
                </shard>
                <shard>
                    <replica>
                        <internal_replication>true</internal_replication>
                        <host>172.17.2.144</host>
                        <port>9000</port>
                    </replica>
                </shard>
                <shard>
                    <internal_replication>true</internal_replication>
                    <replica>
                        <host>172.17.2.145</host>
                        <port>9000</port>
                    </replica>
                </shard>
                <shard>
                    <internal_replication>true</internal_replication>
                    <replica>
                        <host>172.17.2.146</host>
                        <port>9000</port>
                    </replica>
                </shard>
            </my_cluster>
        </clickhouse_remote_servers>
    
        <!--zookeeper相关配置-->
        <zookeeper-servers>
            <node index="1">
                <host>172.17.2.63</host>
                <port>2182</port>
            </node>
            <node index="2">
                <host>172.17.2.64</host>
                <port>2182</port>
            </node>
            <node index="3">
                <host>172.17.2.65</host>
                <port>2182</port>
            </node>
        </zookeeper-servers>
    
        <macros>
            <shard>04</shard>
            <layer>04</layer>
            <replica>172.17.2.146</replica>
        </macros>
    
        <networks>
            <ip>::/0</ip>
        </networks>
    
        <clickhouse_compression>
            <case>
                <min_part_size>10000000000</min_part_size>
                <min_part_size_ratio>0.01</min_part_size_ratio>
                <method>lz4</method>
            </case>
        </clickhouse_compression>
    
    </yandex>
    
    <!-- 其中大部分配置一样,以下的配置根据节点的IP/域名具体配置 -->
    <macros>
        <shard>04</shard>
        <layer>04</layer>
        <replica>172.17.2.146</replica>
    </macros>
    

    注意:为什么直接vim /etc/metrika.xml一个新文件,这里很难去理解,有点莫名其妙,其实如果仔细看过clickhouse的配置文件/etc/clickhouse-server/config.xml就能明白,有这么一段被注释的配置说明:

    <!-- If element has 'incl' attribute, then for it's value will be used corresponding substitution from another file.
             By default, path to file with substitutions is /etc/metrika.xml. It could be changed in config in 'include_from' element.
             Values for substitutions are specified in /yandex/name_of_substitution elements in that file.
          -->
    

    参考单机版启动服务

    验证

    在每个节点启动clickhouse客户端,和单节点启动完全一样,查询集群信息

    clickhouse-client -h 127.0.0.1 --port 9000 -u default -m
    
    select 1;
    select * from system.clusters;
    

    在这里插入图片描述

    使用

    简介

    ClickHouse有多少CPU,吃多少资源,所以飞快;
    ClickHouse不支持事务,不存在隔离级别。ClickHouse的定位是分析性数据库,而不是严格的关系型数据库。又有人要问了,数据都不一致,统计个毛。举个例子,汽车的油表是100%准确么?为了获得一个100%准确的值,难道每次测量你都要停车检查么?统计数据的意义在于用大量的数据看规律,看趋势,而不是100%准确。
    IO方面,MySQL是行存储,ClickHouse是列存储,后者在count()这类操作天然有优势,同时,在IO方面,MySQL需要大量随机IO,ClickHouse基本是顺序IO。
    有人可能觉得上面的数据导入的时候,数据肯定缓存在内存里了,这个的确,但是ClickHouse基本上是顺序IO,用过就知道了,对IO基本没有太高要求,当然,磁盘越快,上层处理越快,但是99%的情况是,CPU先跑满了(数据库里太少见了,大多数都是IO不够用)。

    创建库

    单机版
    CREATE/ATTACH DATABASE test_db ENGINE = Ordinary;
    
    集群版本
    create database clj_test on cluster my_cluster
    
    删除分布式数据库:
    drop database clj_test on cluster my_cluster
    删除分布式表:
    drop table clj_test.news on cluster my_cluster
    

    ATTACH 也可以建库,但是metadata目录下不会生成.sql文件,一般用于metadata元数据sql文件被删除后,恢复库表结构使用

    创建本地表

    单机版本
    CREATE TABLE test01( id UInt16,col1 String,col2 String,create_date date ) ENGINE = MergeTree(create_date, (id), 8192);
    

    ENGINE:是表的引擎类型,

    1. MergeTree:最常用的,MergeTree要求有一个日期字段,还有主键。
    2. Log引擎没有这个限制,也是比较常用。
    3. ReplicatedMergeTree:MergeTree的分支,表复制引擎。
    4. Distributed:分布式引擎。

    create_date:是表的日期字段,一个表必须要有一个日期字段。
    id:是表的主键,主键可以有多个字段,每个字段用逗号分隔。
    8192:是索引粒度,用默认值8192即可。

    创建分布式表

    CREATE TABLE IF NOT EXISTS clj_test.news ON CLUSTER my_cluster \
    ( \
        `key` String, \
        `title` String, \
        `publish_time` String, \
        `publish_date` String \
    ) \
    ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/news', '{replica}') \
    PARTITION BY publish_date \
    ORDER BY key \
    SETTINGS index_granularity = 8192
    

    cluster:配置文件中的群集名称。
    ENGINE后面跟着的参数,是提供给ZooKeeper作区分的该表的路径,对于不同分片上的表,都必须要有不同的路径,所以路径都必须唯一。第一个参数的/clickhouse/tables是官方要求的固定前缀,后面jojo_record是自己表名,表名前面其实还可以加分片名,总的来说可以写成:/clickhouse/tables/shard/table_name 。 第二个参数{replica}指的是副本名称,{副本名}是直接引用配置文件中的你自己配置的副本名称信息

    ClickHouse分布式表的本质并不是一张表,而是一些本地物理表(分片)的分布式视图,本身并不存储数据。 支持分布式表的引擎是Distributed
    create table clj_test.news2 on cluster my_cluster( \
        `key` String, \
        `title` String, \
        `publish_time` String, \
        `publish_date` String \
    )ENGINE Distributed(my_cluster, clj_test, news, rand());
    

    在这里插入图片描述

    概念

    1. clickhouse的cluster环境中,每台server的地位是等价的,即不存在master-slave之说,是multi-master模式。
    2. 各replicated表的宿主server上要在hosts里配置其他replicated表宿主server的ip和hostname的映射。
    3. 上面描述的在不同的server上建立全新的replicated模式的表,如果在某台server上已经存在一张replicated表,并且表中已经有数据,这时在另外的server上执行完replicated建表语句后,已有数据会自动同步到其他server上面。
    4. 如果zookeeper挂掉,replicated表会切换成read-only模式,不再进行数据同步,系统会周期性的尝试与zk重新建立连接。
    5. 如果在向一张replicated表insert数据的时候zookeeper挂掉,这时候会抛一个异常,等到与zk重新建立连接以后,系统(其他replicated表所在server)会检查本地文件与预期文件(保存在zk上)的差别,如果是轻微的差别,直接同步覆盖,如果发现有数据块损坏或者识别不了,则将这些数据文件移动到“detached”子目录,然后重新根据zk所记录的文件信息进行副本的同步。
    6. drop掉某一台server上的replicated表,不会对其他server上面的replicated表造成影响。
    更多相关内容
  • xcode 创建静态和动态

    千次阅读 2014-11-24 11:51:35
    1、linux中静态和动态区别: 从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。分静态和动态两种。 静态:这类库的名字一般是libxxx.a;利用静态函数编译成的文件比较大,因为整个...

    xcode 创建静态库和动态库

    image

    1、linux中静态库和动态库区别:

    库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。

    静态库:这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。

    动态库:这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。

    2、iOS开发中静态库和动态库区别:

    静态库和动态库是相对编译期和运行期的:静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库;而动态库在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。

    静态库 好处:

    i.模块化,分工合作,提高了代码的复用及核心技术的保密程度

    ii.避免少量改动经常导致大量的重复编译连接

    iii.也可以重用,注意不是共享使用

    动态库 好处:

    i.使用动态库,可以将最终可执行文件体积缩小,将整个应用程序分模块,团队合作,进行分工,影响比较小

    ii.使用动态库,多个应用程序共享内存中得同一份库文件,节省资源

    iii.使用动态库,可以不重新编译连接可执行程序的前提下,更新动态库文件达到更新应用程序的目的。

    iv.应用插件化

    v.软件版本实时模块升级

    vi.共享可执行文件 在其它大部分平台上,动态库都可以用于不同应用间共享,这就大大节省了内存。从目前来看,iOS仍然不允许进程间共享动态库,即iOS上的动态库只能是私有的,因为我们仍然不能将动态库文件放置在除了自身沙盒以外的其它任何地方。 不过iOS8上开放了App Extension功能,可以为一个应用创建插件,这样主app和插件之间共享动态库还是可行的。

    3、xcode创建静态库

    打开Xcode, 选择File ----> New ---> Project。 新建工程。 选择iOS ----> Framework & Library ---> Cocoa Touch Static Library。 点击Next。创建工程: image

    新增2个类作为我们的一个静态类文件: image

    其中LogLib.h的代码如下:(作为公开存在) image

    LogLib.m实现方法如下,变成静态库后该文件隐藏: image

    然后选择真机进行静态库的创建:(command + B) image

    这个时候会出现如下的错误提示: image

    按照错误的提示得知我们需要在iOS8.1下build需要选择证书: image

    好了,在Product下会存在libStaticLib.a文件: image

    这只是真机下的一个静态库,同样选择模拟器,command + B,生成模拟器下的静态库。

    找到这2个新建的静态库文件: image

    分别用2个.a加入到其他项目在不同运行坏境选择不同的.a静态库明显不明智,打开终端,输入以下命令行进行整合:

    lipo -create 真机.a路径 模拟器.a路径 -output 整合的.a路径

    lipo -create /Users/fangdd/Library/Developer/Xcode/DerivedData/StaticLib-ercfdooewtvlxmakqvyxkohcagph/Build/Products/Debug-iphoneos/libStaticLib.a /Users/fangdd/Library/Developer/Xcode/DerivedData/StaticLib-ercfdooewtvlxmakqvyxkohcagph/Build/Products/Debug-iphonesimulator/libStaticLib.a -output /Users/fangdd/Desktop/staticLib.a
    

    会在 整合的.a路径下找到合体的静态库。

    将生产的静态库及相应的头文件加入到我们的测试项目中,运行得到: image

    完毕.

    4、xcode创建动态库

    打开Xcode, 选择File ----> New ---> Project。 新建工程。 选择iOS ----> Framework & Library ---> Cocoa Touch Framework。 点击Next。创建工程: image

    命名为DymicLib: image

    同样的添加新的2个类作为测试: image

    将头文件作为公共的头文件,提供给外部调用: image

    运行后变生成了一个动态库,找到Product下的DymicLib.framework所在的目录: image

    注意这个只是运行坏境下的动态库(模拟器和真机),下面建立新的TARGETS:命名为CommonDymicLib: image

    将之前生成的DymicLib加入到新的CommonDymicLib中: image

    CommonDymicLib添加新的脚本来实现模拟器和真机合并: imageimage

    脚本如下:

    # Sets the target folders and the final framework product.
    FMK_NAME=${PROJECT_NAME}
    
    # Install dir will be the final output to the framework.
    # The following line create it in the root folder of the current project.
    INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
    
    # Working dir will be deleted after the framework creation.
    WRK_DIR=build
    DEVICE_DIR=${WRK_DIR}/Release-iphoneos/$    {FMK_NAME}.framework
    SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
    
    # -configuration ${CONFIGURATION}
    # Clean and Building both architectures.
    # 分别编译生成真机和模拟器使用的framework
    xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build
    xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build
    
    # Cleaning the oldest.
    if [ -d "${INSTALL_DIR}" ]
    then
    rm -rf "${INSTALL_DIR}"
    fi
    
    mkdir -p "${INSTALL_DIR}"
    
    cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
    
    # Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
    # 使用lipo命令将其合并成一个通用framework
    # 最后将生成的通用framework放置在工程根目录下新建的Products目录下
    lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
    
    rm -r "${WRK_DIR}"


    选择iOS Device运行: image

    找到生成的CommonDymicLib下的动态库DymicLib.framework: image

    在测试项目中将DymicLib.framework加入: image

    运行即可!image

    心得:这个时候所谓的动态库其实意义就是升级版的静态库,因为动态库使用的前提是项目在发布前添加到项目中,这和我们所谓的插件(即插即用,随时在自己的服务器上下载一个动态库运行,而不需要重新打包,我们可以选择在需要的时候再加载动态库)完全是两码事。

    插件实现方式:使用dlopen加载动态库,动态库中真正的可执行代码为DymicLib.framework/DymicLib文件,因此使用dlopen时如果仅仅指定加载动态库的路径为DymicLib.framework是没法成功加载的。将我们创建的动态库放在我们的服务器,项目上线后再下载这个动态库到我们的Documents文件夹中,使用如下代码动态使用动态库

    #import <dlfcn.h>
    
    NSString *documentsPath = [NSString stringWithFormat:@"%@/Documents/DymicLib.framework/DymicLib",NSHomeDirectory()];
    void * libHandle = NULL;
    libHandle = dlopen([documentsPath cStringUsingEncoding:NSUTF8StringEncoding], RTLD_NOW);
    if (libHandle == NULL) {
        char *error = dlerror();
        NSLog(@"dlopen error: %s", error);
    } else {
        NSLog(@"dlopen load framework success.");
    }


    使用  动态库 中的类:

    Class rootClass = NSClassFromString(@"DymicLog");
    if (rootClass) {
        id object = [[rootClass alloc] init];
        [(DymicLog *)object relog:@"hello world"];
    }



    展开全文
  • Linux下静态、共享创建与应用

    千次阅读 多人点赞 2019-02-15 09:53:56
    2 用例子说明两种创建与应用 2.1 静态创建与应用 2.1.1 静态创建 2.1.2 静态的应用 2.1.3 静态搜索路径 补充说明 2.2 共享创建与应用 2.2.1 共享创建 2.2.2 共享的应用 2.2.2 ...

    目录

    1 什么是静态库和共享库

    1.1 为什么要有静态库和共享库

    1.2  静态库和共享库的区别

    2 用例子说明两种库的创建与应用

    2.1 静态库的创建与应用

    2.1.1 静态库的创建

    2.1.2 静态库的应用

    2.1.3 静态库搜索路径

    补充说明

    2.2 共享库的创建与应用

    2.2.1 共享库的创建

    2.2.2 共享库的应用

    2.2.2 共享库搜索路径

    补充说明


    1 什么是静态库和共享库

    1.1 为什么要有静态库和共享库

            还是先来说一下我自己对静态库和共享库的理解。

            为什么会有静态库和共享库这两个东西呢?我们都知道,为了避免一些重复性的工作并且便于编程,开发人员定义了一系列的标准函数以供调用,这些函数都放在相应的函数库中,而我们在进行开发时也会经常用到这些标准函数,那么就需要找到函数的定义,那么编译器该怎么去找到函数的定义呢?

            一种方法是让编译器自动识别函数。比如说我在程序中调用了printf函数,那么当编译器识别到对printf函数的调用时,就直接生成printf函数定义的相应代码,这种方法听起来非常简单,但是实际上缺点也很多,因为标准库函数是会更新的,一旦增加、删除或者修改了其中某一个标准函数,那么相应的编译器也必须进行改变,不然无法识别新的函数,这也是相当复杂的,需要从编译器进行改变,那有没有办法可以将标准函数的改变与编译器分开呢?这就是第二种方法了。

             第二种方法是直接将所有的标准函数都放在一个源文件中,然后编译生成一个可重定位目标文件(.o),当编译器识别到某一个被调用的函数时,就直接去这个.o文件中寻找该函数的定义,显然在这种方法下,即使修改了标准函数,编译器也不需要进行改变了,这就解决了第一种方法带来的问题。但是这种方法也有缺点,因为标准函数是非常多的,比如说a.cpp中只用了一个printf函数,b.cpp中只用了一个scanf函数,当它们各自编译结束后,二者生成的可执行文件中都包含着所有标准函数集合的一个副本,这是对磁盘空间的一种浪费,不仅如此,当可执行文件运行,程序加载到内存中时,是会将所有标准函数一起加载到内存中的,这也是对内存资源的一种极大浪费,不容忽视。除此之外,当某个标准函数发生改变的时候,都需要对所有函数进行重新编译,这个过程也非常耗时而不易维护。

            显而易见,第二种方法的主要缺点就是将所有函数都放在一起太浪费资源,因此就考虑将这些函数都各自分开成一个个的小模块,到时候按需调用。但是也不能每个函数自成一个模块,这样显然也会很麻烦,因此就可以考虑将相关的函数放在一个模块中,然后一个或多个模块封装到一个库中,这个库显然就是多个模块文件(可重定位目标文件)的集合,也叫静态库(.a)。

            值得注意的是,静态库也不知道用户到底会调用哪个函数(模块),所以其中也很可能存在用户不需要的模块,但在链接时,链接器将只会复制被程序引用的目标模块,这样一来,相较于第二种方法,程序所生成的可执行文件在内存和磁盘中的空间大小将显著降低。

            这样看起来,静态库似乎已经将前两种方法的缺点都改善了,但它并非是最好的,举个例子,现在有a.cpp和b.cpp都依赖于同一个静态库lib.a中的相同模块m,各自生成可执行文件a和b,那么不管程序是在编译时还是运行时,磁盘中和内存中m都会存在两份,各自存在于可执行文件a和b中。这显然也是一种资源的浪费,而共享库(.so)则很好的解决了这个问题,共享库在程序运行时,会被加载到内存中任意地址处,此时,内存中就存在着该共享库的副本,所有引用该共享库的可执行文件都共享这个库,这样一来,原本需要在磁盘和内存中分别存在2份的模块m如今只需在磁盘和内存中各存1份即可。

    1.2  静态库和共享库的区别

    • 静态库被程序静态链接于编译时,而共享库被动态链接于运行时;
    • 静态链接时,需要把所有对静态库的引用内容都嵌入到最终的可执行文件中,且相同模块并不共用,都有相应的副本,因此相应的可执行文件在磁盘和内存中所占空间较大;而动态链接是发生在运行时的,并且是共享的,因此相应的可执行文件在磁盘中所占空间较小;
    • 由于静态链接是在编译时完成的,因此可执行文件中以及包含有所需的静态库,可执行文件可以单独运行;由于动态链接是在程序运行时完成的,可执行文件在加载入内存运行时才会链接共享库,因此可执行文件必需共享库的支持,不能单独运行;
    • 当静态库中某个模块更新后,需要重新编译链接生成相应的可执行文件;另一方面若共享库中某个模块更新了,只要接口没有改变,就不需要重新编译链接生成可执行文件;
    • 静态链接比动态链接速度稍快
    • 静态库中不能包含共享库,而共享库中可以包含静态库

            综合以上区别,可以发现动态链接的性能是明显优于静态链接的,但是这不一定就说明静态链接一定比不上动态链接了。如果库本身就比较小且不经常改变,基于速度的角度,应当选择静态链接,否则还是应当选择动态链接,由于是大型软件需要经常维护、扩展之类的情况。除此之外,静态链接的一个显著优点是其相应的可执行文件已经是完整的,包含所有所需的模块,因此可以很方便地移动到其他地方执行。

    2 用例子说明两种库的创建与应用

             建立以下文件树,其中bin文件夹用于存放可执行程序,lib文件夹用于存放库文件,src文件夹用于存放源代码,如图所示:

            在src文件夹中,包含了四则运算的四个源文件.cpp以及一个主函数源文件main.cpp,其中main.cpp的代码如下:

         四则运算分别定义于相应的.cpp文件中。现在以该例来说明静态库与共享库如何创建并应用的。

    2.1 静态库的创建与应用

    2.1.1 静态库的创建

          静态库实际上就是一个或多个.o文件的集合。因此第一步是将各模块编译为.o文件。

          编译命令为g++ -c xxx.cpp    如下:

             此时就可以将add.o、div.o......四个模块打包到静态库中,这里需要用到AR工具,ar的指令详解可参考ar指令说明

    (在使用ar命令时,创建库时常用ar rcs .....,若往库中添加模块时用r即可ar r ....,若要删除库中某一模块用d即可ar d ......)

            在这里使用ar rcs libxxx.a  xx.o xx.o.....  rcs中的r表示向库中添加模块,若模块已存在则替换,c表示创建库文件,s表示生成一个目标文件索引。

             此时可用命令参数t来查看静态库中的模块清单,如下所示:

             此时静态库则创建完成。

    2.1.2 静态库的应用

             静态库的应用即是将main.cpp文件与建立的libcalcu.a静态库进行链接并生成可执行文件运行的过程。

             静态库链接直接使用g++命令即可,不过由于g++在默认情况下是动态链接的,因此如果要进行静态链接那么就需要命令参数-static,如下所示:

            

            此时就在bin文件夹中生成了可执行文件output,加载并运行output,如下:

            为了与动态链接的可执行文件作对比,我们再来看看可执行文件output的大小:      

           可见静态链接后的可执行文件大小为1.6M。

    2.1.3 静态库搜索路径

    1.先去找链接命令行中的参数-L。-L参数可直接指定静态库的搜索路径,-L. 表示在当前目录下搜索(注意L后面有个点),-L后面直接加上路径表示在该路径下搜索(L后面没有点),比如-L../lib libcalcu.a 表示在当前目录的同级目录lib中搜索libcalcu.a静态库,这里在-L指明了搜索路径的情况下,静态库的命名格式为libxxx.a,那么就可以用-l命令将其简化为-lxxx,即可将-L../lib libcalcu.a 简化为-L../lib -lcalcu;

    2.再找静态链接的环境变量LIBRARY_PATH下的路径;(个人感觉这里设置环境变量意义不大)

    3.再找系统默认路径/lib、/usr/lib、/usr/local/lib。

    补充说明

             在进行静态链接时一定要注意命令行中库文件放在后面,被依赖的文件也要放在后面,这里的a依赖于b是指b中定义了a中所引用的一个符号。如果文件之间依赖关系复杂,可以将 多个依赖关系复杂的文件放在一个静态库中,或者在命令行中根据依赖关系多次指明被依赖文件也是可以的,比如说x.o依赖于y.a,同时y.a依赖于z.a,并且z.a由依赖于y.a,那么此时这三个文件在命令行中的链接顺序就可以是x.o y.a z.a y.a。

            之所以这样,是因为在符号解析过程中,链接器维护一个可重定位目标文件的集合E,这个集合中的文件最终合并为可执行文件;一个未解析符号集合U,该集合中存放着被引用但是未被定义的符号;以及一个一个已经被定义的符号D,在初始状态下,三个集合均为空。所谓符号,就像变量名、函数名都是符号。

            然后链接器从左到右按照各个可重定位目标文件(.o)和静态库文件(.a)在命令行上出现的顺序来对每个文件进行扫描,如果输入文件为可重定位目标文件,那么链接器就会将该文件放到集合E中,并且将该输入文件中的符号定义和引用情况反应在集合U和集合D中;

            如果输入文件为静态库文件,那么链接器就会扫描该静态库文件中的各成员文件(.o),将成员文件中的符号与U中已被引用但是未定义的符号进行匹配,如果该静态库中某个成员文件定义了U中某个已被引用但未被定义的符号,那么链接器就将该成员文件放到集合E中,然后在U中删除该符号,D中添加该符号,再继续扫描下一个成员文件,这样一直反复进行扫描下去,直到U和D中集合都不再变化,就将多余的成员文件抛弃,然后就继续扫描下一个输入文件了。

            若文件a依赖于b,那么就说明a中存在某一符号的引用,b中存在该符号的定义。如果先扫描到符号的定义,那么就会将该符号放到D中,而由于每次扫描都是与U中的符号进行匹配,因此即使后面再扫描到该符号的引用,也会直接将该符号又放入U中,由于符号的定义已经在D中了,因此到最后该符号依然存在于U中,U中非空,说明链接中存在被引用但是未定义的符号,从而该符号被认为是未定义的符号而报错。

    2.2 共享库的创建与应用

    2.2.1 共享库的创建

            创建共享库的输入文件可为.c/.cpp文件,用命令参数-shared表示创建共享库,-fpic参数也是必要的,指示编译器生成与位置无关的代码,这样才能实现应用程序之间的资源共享,如下所示:

            可见此时lib文件夹下存在的libcalcusr.so即是创建的共享库。

            值得一提的是,虽然-static和-shared这一对命令参数恰好一个代表静态一个代表共享,但是二者使用的时机是完全不同的:-static使用在生成可执行文件时,而-share则使用在创建共享库时,而静态库的创建是使用的ar命令。

    2.2.2 共享库的应用

            共享库创建完成后,就要将其链接到main.cpp文件中来生成可执行文件了,如下:

            可以看到,可执行文件output_s已经生成,并且其大小明显小于静态链接所生成的可执行文件。

            这里尤其需要注意的是./libcalcusr.so,这里直接指定了可执行文件所要链接的共享库的搜索路径在当前目录下(如果将./libcalcusr.so改为libcalcusr.so,虽然生成可执行文件时不会出错,但是最终可执行文件运行时是无法找到共享库的,即链接时正常,运行时出错),同样,如果将共享库文件移至src下,那么就应当将其改为../src/libcalcusr.so,总之,在最后需要指定共享库的搜索路径,否则在加载执行可执行文件时会出现错误。

             加载运行如下:

    2.2.2 共享库搜索路径

    1.先找编译目标代码时指定的动态库搜索路径。这里所指的编译时实际就是指的在最后用共享库和main.cpp文件生成可执行文件时直接指定共享库的搜索路径,需要注意的是,这里指定共享库的搜索路径必须同时指出链接时路径和运行时路径,链接器根据给出的链接时路径找到共享库这样才能生成可执行文件,程序运行时需根据运行时路径找到共享库才能运行可执行文件。有两种方法,一种是如上所述直接给出共享库的路径,这里就相当于路径既代表了链接时路径也代表了运行时路径;另一种方法是使用命令参数-L来指定链接时路径,这点和静态库类似就不多说了,然后使用命令参数-Wl(小写L),-rpath=xxxx来指定运行时路径,比如说这里的libcalcusr.so在lib文件夹下,main.cpp在src文件夹下,我要将可执行文件最终输出在bin文件夹下,当前目录为src,就使用以下命令即可:g++ -o  ../bin/output_s main.cpp -L../lib -lcalcusr -Wl,-rpath=../lib,其中的-lcalcusr也是在-l参数下的库名简写。

    2.再找环境变量LD_LIBRARY_PATH指定的动态库搜索路径。如果此时已经生成了可执行文件,但是可执行文件找不到共享库从而无法运行,那么就可以设置环境变量LD_LIBRARY_PATH来指出共享库的搜索路径。举个例子,生成的可执行文件在bin文件夹下,不管之前链接时是如何指定搜索路径的,总之现在无法找到共享库,而此时共享库位于bin文件夹下,那么就可以使用指令export LD_LIBRARY_PATH=../bin ,这里的右侧路径是相对于当前路径而言的。不过这种方式是治标不治本的, 只是当前链接可行,后面就不行了。

    3.再找配置文件/etc/ld.so.conf中指定的动态库搜索路径。打开/etc/ld.so.conf,在文件末尾处加上共享库路径,保存后再在命令行中输入ldconfig命令执行即可。

    4.最后寻找默认的动态库搜索路径/usr/lib、/lib(分先后顺序)。

             此外,如果我们并不知道可执行文件需要链接哪些共享库,就可以使用ldd指令,来查看一个可执行文件所依赖的共享库,这样也方便解决无法找到共享库的问题。

            如图所示,可以看到可执行文件output_s所依赖的共享库。

    补充说明

            以上链接共享库的方法为隐式链接共享库,当然还有显式链接共享库了。显示是指在程序中直接写出相关的链接代码,在Linux下,可用dlopen函数通过指定共享库路径来加载和链接共享库,加载成功后可以得到相应共享库的句柄,然后就可以根据该句柄并调用dlsym函数来获取相应共享库中指定符号的地址(往往就是共享库中某函数地址),通过这个地址就可以调用相应的函数了,从而实现共享库的应用。

    展开全文
  • 讨论方案:直接长久存储 表schema:一般按天创建分区与表命名。库名:buffer,表名:初步考虑格式为:buffer日期业务表名,待定。 明细层(ODS, Operational Data Store,DWD: data warehouse detail) 概念:是数据...

    一、前言

    现在说数仓,更多的会和数据平台或者基础架构搭上,已经融合到整个基础设施的搭建上。这里呢,我们不说Hadoop各种组件之间的配合,我们就简单说下数仓分层的意义价值和该如何设计分层。

    二、数仓建模

    说到数仓建模,就得提下经典的2套理论:

    • 范式建模
      Inmon提出的集线器的自上而下(EDW-DM)的数据仓库架构。

    • 维度建模
      Kimball提出的总线式的自下而上(DM-DW)的数据仓库架构。

    数仓的建模或者分层,其实都是为了更好的去组织、管理、维护数据,实际开发时会整合2种方式去使用,当然,还有些其他的,像Data Vault模型、Anchor模型,暂时还没有应用过,就不说了。

    维度建模,一般都会提到星型模型、雪花模型,星型模型做OLAP分析很方便。

    三、数仓分层

    简单点儿,直接ODS+DM就可以了,将所有数据同步过来,然后直接开发些应用层的报表,这是最简单的了;当DM层的内容多了以后,想要重用,就会再拆分一个公共层出来,变成三层架构,最近看了本阿里的书,《大数据之路》,里面有很多数仓相关的内容,很不错,参考后,目前使用的分层模式如下:

    在这里插入图片描述

    按照这种分层方式,我们的开发重心就在 DWD 层,就是明细数据层,这里主要是一些宽表,存储的还是明细数据;到了 DWS 层,我们就会针对不同的维度,对数据进行聚合了。按道理说,DWS层算是集市层,这里一般按照主题进行划分,属于维度建模的范畴;ADS就是偏应用层,各种报表的输出。

    四、数仓的基本特征

    数据仓库有4个基本特征:面向主题的、集成的、相对稳定的、记录历史的,而数据仓库的价值正是基于这4个特征体现的。

    1、高效的数据组织和管理
    面向主题的特性决定了数据仓库拥有业务数据库所无法拥有的高效的数据组织形式,更加完整的数据体系,清晰的数据分类和分层机制。因为所有数据在进入数据仓库之前都经过清洗和过滤,使原始数据不再杂乱无章,基于优化查询的组织形式,有效提高数据获取、统计和分析的效率。

    2、时间价值
    数据仓库的构建将大大缩短获取信息的时间,数据仓库作为数据的集合,所有的信息都可以从数据仓库直接获取,数据仓库的最大优势在于一旦底层从各类数据源到数据仓库的ETL流程构建成型,那么每天就会有来自各方面的信息通过自动任务调度的形式流入数据仓库,从而使一切基于这些底层信息的数据获取的效率达到迅速提升。
    从应用来看,使用数据仓库可以大大提高数据的查询效率,尤其对于海量数据的关联查询和复杂查询,所以数据仓库有利于实现复杂的统计需求,提高数据统计的效率。

    3、集成价值
    数据仓库是所有数据的集合,包括日志信息、数据库数据、文本数据、外部数据等都集成在数据仓库中,对于应用来说,实现各种不同数据的关联并使多维分析更加方便,为从多角度多层次地数据分析和决策制定提供的可能。

    4、历史累积价值
    记历史是数据仓库的特性之一,数据仓库能够还原历史时间点上的产品状态、用户状态、用户行为等,以便于能更好的回溯历史,分析历史,跟踪用户的历史行为,更好地比较历史和总结历史,同时根据历史预测未来。

    五、数据仓库用途

    • 整合公司所有业务数据,建立统一的数据中心
    • 产生业务报表,用于作出决策
    • 为网站运营提供运营上的数据支持
    • 可以作为各个业务的数据源,形成业务数据互相反馈的良性循环
    • 分析用户行为数据,通过数据挖掘来降低投入成本,提高投入效果
    • 开发数据产品,直接或间接地为公司盈利

    六、数仓分层的好处

    对数据进行分层的一个主要原因就是希望在管理数据的时候,能对数据有一个更加清晰的掌控,详细来讲,主要有下面几个原因:

    • 清晰数据结构:每一个数据分层都有它的作用域,这样我们在使用表的时候能更方便地定位和理解。
    • 数据血缘追踪:简单来讲可以这样理解,我们最终给业务呈现的是一张能直接使用的张业务表,但是它的来源有很多,如果有一张来源表出问题了,我们希望能够快速准确地定位到问题,并清楚它的危害范围。
    • 减少重复开发:规范数据分层,开发一些通用的中间层数据,能够减少极大的重复计算。
    • 把复杂问题简单化:将一个复杂的任务分解成多个步骤来完成,每一层只处理单一的步骤,比较简单和容易理解。而且便于维护数据的准确性,当数据出现问题之后,可以不用修复所有的数据,只需要从有问题的步骤开始修复。
    • 屏蔽原始数据的异常:屏蔽业务的影响,不必改一次业务就需要重新接入数据。

    数据体系中的各个表的依赖就像是电线的流向一样,我们都希望它是规整、流向清晰、便于管理的,如下图。

    在这里插入图片描述
    但是,最终的结果大多却是依赖复杂、层级混乱,想梳理清楚一张表的生成途径会比较困难,如下图:

    在这里插入图片描述

    七、如何分层

    理论抽象

    我们可以从理论上对数仓来做一个抽象,可以把数据仓库分为下面三个层,即:数据运营层、数据仓库层和数据产品层

    在这里插入图片描述

    1. 操作数据层(ODS)

    “面向主题的”,数据运营层,也叫ODS层,是最接近数据源中数据的一层,数据源中的数据,经过抽取、洗净、传输,也就说传说中的 ETL 之后,装入本层。

    本层的数据,总体上大多是按照源头业务系统的分类方式而分类的。但是,这一层面的数据却不等同于原始数据。在源数据装入这一层时,要进行诸如去噪(例如有一条数据中人的年龄是 300 岁,这种属于异常数据,就需要提前做一些处理)、去重(例如在个人资料表中,同一 ID 却有两条重复数据,在接入的时候需要做一步去重)、字段命名规范等一系列操作。

    2. 数据仓库层(DW/CDM)

    这是数据仓库的主体。在这里,从 ODS 层中获得的数据按照主题建立各种数据模型,在这一层和维度建模会有比较深的联系。

    3. 数据产品/集市层(APP/ADS)

    这一层是提供为数据产品使用的结果数据。在这里,主要是提供给数据产品和数据分析使用的数据,一般会存放在 ES、MySQL等系统中供线上系统使用,也可能会存在 Hive 或者 Druid 中供数据分析和数据挖掘使用。如我们经常说的报表数据,或者说那种大宽表,一般就放在这里。

    另外,我们在实际分层过程中,也可以根据我们的实际数据处理的流程进行分层。

    八、举个例子

    网上的例子很多,以下是某位大牛早期参与设计的数据分层例子。

    我们分析一下当初的想法,以及这种设计的缺陷。

    大佬当初的设计总共分了 6 层,其中去掉元数据后,还有5层。下面分析一下当初的一个设计思路。

    在这里插入图片描述

    缓冲层(buffer)

    概念:又称为接口层(stage),用于存储每天的增量数据和变更数据,如Canal接收的业务变更日志。
    数据生成方式:直接从kafka接收源数据,需要业务表每天生成update、delete、inseret数据,只生成insert数据的业务表,数据直接入明细层。
    讨论方案:只把canal日志直接入缓冲层,如果其它有拉链数据的业务,也入缓冲层。
    日志存储方式:使用Impala外表,parquet文件格式,方便需要MR处理的数据读取。
    日志删除方式:长久存储,可只存储最近几天的数据。讨论方案:直接长久存储
    表schema:一般按天创建分区库与表命名。库名:buffer、表名:初步考虑格式为:buffer日期业务表名,待定。


    明细层(ODS, Operational Data Store,DWD: data warehouse detail)

    概念:是数据仓库的细节数据层,是对STAGE层数据进行沉淀,减少了抽取的复杂性,同时ODS/DWD的信息模型组织主要遵循企业业务事务处理的形式,将各个专业数据进行集中,明细层跟stage层的粒度一致,属于分析的公共资源
    数据生成方式:部分数据直接来自kafka,部分数据为接口层数据与历史数据合成。
    canal日志合成数据的方式待研究。

    讨论方案:canal数据的合成方式为:每天把明细层的前天全量数据和昨天新数据合成一个新的数据表,覆盖旧表。同时使用历史镜像,按周/按月/按年 存储一个历史镜像到新表。
    日志存储方式:直接数据使用impala外表,parquet文件格式,canal合成数据为二次生成数据,建议使用内表,下面几层都是从impala生成的数据,建议都用内表+静态/动态分区。
    日志删除方式:长久存储。
    表schema:一般按天创建分区,没有时间概念的按具体业务选择分区字段。
    库与表命名:库名:ods、表名:初步考虑格式为ods日期业务表名,待定。
    旧数据更新方式:直接覆盖


    轻度汇总层(MID或DWB, data warehouse basis)

    概念:轻度汇总层数据仓库中DWD层和DM层之间的一个过渡层次,是对DWD层的生产数据进行轻度综合和汇总统计(可以把复杂的清洗,处理包含,如根据PV日志生成的会话数据)。轻度综合层与DWD的主要区别在于二者的应用领域不同,DWD的数据来源于生产型系统,并未满意一些不可预见的需求而进行沉淀;轻度综合层则面向分析型应用进行细粒度的统计和沉淀。
    数据生成方式:由明细层按照一定的业务需求生成轻度汇总表。明细层需要复杂清洗的数据和需要MR处理的数据也经过处理后接入到轻度汇总层。
    日志存储方式:内表,parquet文件格式。
    日志删除方式:长久存储。
    表schema:一般按天创建分区,没有时间概念的按具体业务选择分区字段。
    库与表命名:库名:dwb,表名:初步考虑格式为:dwb日期业务表名,待定。
    旧数据更新方式:直接覆盖。


    主题层(DM,data market或DWS, data warehouse service)

    概念:又称数据集市或宽表。按照业务划分,如流量、订单、用户等,生成字段比较多的宽表,用于提供后续的业务查询,OLAP分析,数据分发等。
    数据生成方式:由轻度汇总层和明细层数据计算生成。
    日志存储方式:使用impala内表,parquet文件格式。
    日志删除方式:长久存储。
    表schema:一般按天创建分区,没有时间概念的按具体业务选择分区字段。
    库与表命名:库名:dm、表名:初步考虑格式为:dm日期业务表名,待定。
    旧数据更新方式:直接覆盖。


    应用层(App)

    概念:应用层是根据业务需要,由前面三层数据统计而出的结果,可以直接提供查询展现,或导入至Mysql中使用。
    数据生成方式:由明细层、轻度汇总层,数据集市层生成,一般要求数据主要来源于集市层。
    日志存储方式:使用impala内表,parquet文件格式。
    日志删除方式:长久存储。
    表schema:一般按天创建分区,没有时间概念的按具体业务选择分区字段。
    库与表命名:库名:暂定apl,另外根据业务不同,不限定一定要一个库。
    旧数据更新方式:直接覆盖。

    九、如何更优雅一些

    前面提到的一种设计其实相对来讲已经很详细了,但是可能层次会有一点多,而且在区分一张表到底该存放在什么位置的时候可能还有不小的疑惑。我们可以再设计一套数据仓库的分层,同时在前面的基础上加上维表和一些临时表的考虑,来让我们的方案更优雅一些。

    下图,做了一些小的改动,我们去掉了上一节的Buffer层,把数据集市层和轻度汇总层放在同一个层级上,同时独立出来了维表和临时表。

    在这里插入图片描述

    这里解释一下DWS、DWD、DIM和TMP的作用。

    DWS:轻度汇总层,从ODS层中对用户的行为做一个初步的汇总,抽象出来一些通用的维度:时间、ip、id,并根据这些维度做一些统计值,比如用户每个时间段在不同登录ip购买的商品数等。这里做一层轻度的汇总会让计算更加的高效,在此基础上如果计算仅7天、30天、90天的行为的话会快很多。我们希望80%的业务都能通过我们的DWS层计算,而不是ODS。

    DWD:这一层主要解决一些数据质量问题和数据的完整度问题。比如用户的资料信息来自于很多不同表,而且经常出现延迟丢数据等问题,为了方便各个使用方更好的使用数据,我们可以在这一层做一个屏蔽。

    DIM:这一层比较单纯,举个例子就明白,比如国家代码和国家名、地理位置、中文名、国旗图片等信息就存在DIM层中。

    TMP:每一层的计算都会有很多临时表,专设一个DWTMP层来存储我们数据仓库的临时表。

    展开全文
  • 几乎最全的中文NLP资源库

    万次阅读 多人点赞 2020-05-12 10:10:38
    NLP民工的乐园: 几乎最全的中文NLP资源库 词库 工具包 学习资料 在入门到熟悉NLP的过程中,用到了很多github上的包,遂整理了一下,分享在这里。 很多包非常有趣,值得收藏,满足大家的收集癖! 如果觉得有用,...
  • VS2019环境下C++动态链接(DLL)的创建与调用

    万次阅读 多人点赞 2019-12-20 02:17:33
    本文旨在介绍如何在VS2019的环境下建立动态链接以及如何调用动态链接
  • 现实中每个程序都要依赖很多基础的底层,不可能每个人的代码都从零开始,因此的存在意义非同寻常。本质上来说是一种可执行代码的二进制形式,可以被操作系统载入内存执行。有两种:静态(.a、.lib)和动态...
  • ### 目录 一、 基本概念 1. 静态动态区别 2. 的版本 3. iOS 设备的CPU架构 4.... 5.... 6....二、打包framewor静态 1. 创建项目-》创建静态项目 2. 静态如何开发调试? 3. 脚本合...
  • 详见后文:三范式与反范式 2.3 Data Vault模型 DataVault由Hub(关键核心业务实体)、Link(关系)、Satellite(实体属性) 三部分组成 ,是Dan Linstedt发起创建的一种模型方法论,它是在ER关系模型上的衍生,同时...
  • 【Linux】Linux进程的创建与管理

    万次阅读 多人点赞 2018-07-27 19:21:29
    在Linux系统中,除了系统启动之后的第一个进程由系统来创建,其余的进程都必须由已存在的进程来创建,新创建的进程叫做子进程,而创建子进程的进程叫做父进程。那个在系统启动及完成初始化之后,Linux自动创建的进程...
  • 3. 了解并创建Git仓库,以及添加文件到仓库 先来理解一个概念,repository。你可以简单将它理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何...
  • 大家将要读到的是如何使用VMware技术完成一个自动化/流程化(企业内部流程)的虚拟机资源池,这一方案是已经在大型金融企业管理了数千台虚拟机的实际方案。在大多数做云的甲方企业或乙方集成商看来,这就是云计算了...
  • 数据仓库基本知识

    万次阅读 多人点赞 2017-10-31 17:35:04
    因此,企业仍然没有最大化地利用已存在的数据资源,以至于浪费了更多的时间和资金,也失去制定关键商业决策的最佳契机。 于是,企业如何通过各种技术手段,并把数据转换为信息、知识避免各种无知状态和瞎猜行为,...
  • threading:Python线程的基础知识

    千次阅读 2021-05-08 14:05:36
    前面的subprocess主要讲解的是进程知识与进程间的交互。而进程有可以拥有多个线程,所以threading提供了管理多个线程执行的API,允许程序在同一个进程空间并发地运行多个操作。 本篇,将详细的介绍Python线程...
  • App 快捷方式——创建快捷方式

    千次阅读 2019-01-15 18:53:07
    创建一个新的资源文件:  res/xml/shortcuts.xml 。 在此新资源文件中,添加   根元素,其中包含   元素的列表。 每个   元素都包含有关静态快捷方式的信息,包括其图标,描述标签以及它在应用...
  • libevent介绍

    万次阅读 2019-03-17 16:31:04
    一、libevent就是一个基于事件通知机制的,支持/dev/poll、kqueue、event ports、select、poll和epoll事件机制,也因此它是一个跨操作系统的(支持Linux、*BSD、Mac OS X、Solaris、Windows等)。目前应用该的...
  • 访问网络接口和磁盘驱动器等资源是在此环境中虚拟化的,与系统的其余部分隔离,因此您需要将端口映射到外部世界,并明确要将哪些文件“复制”到那个环境。但是,在完成这些之后,您可以期望在其中定义的应用程序的...
  • 3、创建默认堆并在其上以“定位方式”创建2D纹理 4、动态采样器 5、完整代码 1、前言 经过了第二部分教程的“折腾”之后,后面的教程我觉得应该顺畅多了。至少我现在可以一天时间就把教程示例代码调通,并且可以...
  • 【汇总】语料库资源

    千次阅读 2015-06-02 23:40:32
    国内可用免费语料(凡没有标注不可用的链接均可用) (一) 国家语委 1.国家语委现代汉语语料http://www.cncorpus.org/ 现代汉语通用平衡语料现在重新开放网络查询了。重开后的在线检索速度更快,功能更强...
  • 玩PyTorch?你不得不看的PyTorch资源大列表

    万次阅读 多人点赞 2020-02-29 18:16:32
    这里我介绍一个我再GitHub闲逛的时候发现的一个项目,这里面的资源真的是又强又全,惊为天人。 Pytorch & related libraries|Pytorch & 相关 pytorch : Tensors and Dynamic neural networks in Python ...
  • 最近由于公司业务需要,要求封装一个支付SDK,需要用到微信支付和支付宝,之前做过的Framework没有依赖其他第三方的所以比较好做,这次有所不同;一开始我想把支付宝和微信支付的SDK全部融合进来,折腾
  • Android 深刻理解Activity生命周期的作用及意义

    千次阅读 多人点赞 2017-06-05 12:54:48
    我们一般在创建Activity时需要重写该方法做一些初始化的操作,如通过setContentView设置界面布局的资源,初始化所需要的组件信息等。  (2)onStart() ,可见状态  该方法回调表示Activity正在启动,此时Activity...
  • C++静态与动态的区别

    千次阅读 2019-08-31 16:11:52
    现实中每个程序都要依赖很多基础的底层,不可能每个人的代码都从零开始,因此的存在意义非同寻常 。 本质上来说是一种可执行代码的二进制形式,可以被操作系统载入内存执行。有两种:静态(.a、.lib)和...
  • itstack-demo-design Java面经手册 interview Spring手撸专栏 small-spring 四、贡献力量,提交Issue、PR 慢下来,并且有意义的事,我们可以一起来做 2021年10月24日 - 程序员节‍,小傅哥 把文章全部开源到代码 ...
  • AnnotationAwareAspectJAutoProxyCreator对目标对象进行代理对象的创建,对象内部,是封装JDK和CGlib两个技术,实现动态代理对象创建的(创建代理对象过程中,会先创建一个代理工厂,获取到所有的增强器(通知方法...
  • C++静态与动态的区别?

    万次阅读 多人点赞 2018-08-17 20:29:59
    这次分享的宗旨是——让大家学会创建与使用静态、动态,知道静态与动态的区别,知道使用的时候如何选择。这里不深入介绍静态、动态的底层格式,内存布局等,有兴趣的同学,推荐一本书《程序员的自我修养...
  • Python中模块、、包的概念

    千次阅读 2019-10-08 20:37:05
    文章目录一、模块(Moudule)1.模块的概念2.模块的导入3.模块的引用于__name__属性二、(Library)1.的概念2.的分类:3.第三方的安装三、包(Package)1.包的概念2....一、模块(Moudule) ...创建一个模块...
  • PicGo+gitee仓库+Typora 图床创建与使用
  • Python程序设计题库

    万次阅读 多人点赞 2020-03-28 17:39:40
    1、 Python安装扩展常用的是_工具。(pip) 2、 Python标准math中用来计算平方根的函数是____。(sqrt) 3、 Python程序文件扩展名主要有__和两种,其中后者常用于GUI程序。(py、pyw) 4、 Python源代码程序...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 150,577
精华内容 60,230
关键字:

创建资源库的意义

友情链接: matCUDA_User_Guide_0.1.zip