精华内容
下载资源
问答
  • 原标题:深入数据库同步技术(1)- 基础篇 在大约十年前NoSQL概念刚刚提出来的时候,其雄心勃勃的目标就是将关系型数据库(RDB)完全淘汰掉。十年过去了,各类NoSQL产品逐步丰富(K/V,文档,图形,缓存等),它们在跌跌撞...

    原标题:深入数据库同步技术(1)- 基础篇

    2781adf769740aa0c3969f8ca47f3680.png

    在大约十年前NoSQL概念刚刚提出来的时候,其雄心勃勃的目标就是将关系型数据库(RDB)完全淘汰掉。十年过去了,各类NoSQL产品逐步丰富(K/V,文档,图形,缓存等),它们在跌跌撞撞中找到了自己的定位,其当初的愿景也从“No SQL”演变为“Not Only SQL”。关系型数据库活得甚至比原来更加滋润(当然一些关系型数据库也会居安思危,在产品中加入NoSQL特性,比如Oracle)。

    事实上,如果我们的系统需要落地数据,尤其是交易型数据,关系型数据库依然是我们的不二选择。在未来相当长的时间里,我们依然会重度依赖关系型数据库。

    而在数据库的使用领域,数据同步绝对是一个绕不开的话题。

    本文将以大家常见的数据库Oracle和MySQL为例,介绍如何做好数据同步,更确切地讲,是如何做好表数据同步。

    8135406afd67bda21609b363fa6ed279.gif

    一、数据同步涉及的业务场景

    在很多业务场景下,我们都有可能会涉及到数据同步,常见的有:

    ▪ 基于较单纯的同步目的:

    由于业务需要,我们就需要把A库的表同步到B库去,这个目的单一且直接。

    ▪ 出于构建数据总线目的:

    我们知道一般系统中都有一个主数据库,该数据库是一个OLTP库,随时接受终端用户的业务请求,对数据库发生CRUD操作。

    如果可以构建一个数据总线(Data Bus),在主数据库有变更事件发生时,可以将数据变更同步/传播到其他系统,比如:Memcached/Redis(更新缓存),ES(更新索引),通知其他业务方(某系统对某些表数据的变更事件很感兴趣)。

    数据总线机制可以看做是实现数据发布,数据订阅,数据通知的基础载体。

    ▪ 其他目的:

    我们可以通过数据同步实现Master/Slave,实现去O,或者实现异地机房间的数据同步(为了灾备或构建双主机房)等。

    二、数据同步的分类

    我们可以从不同维度和层面对数据同步进行分类,比如:

    ▪离线同步和在线同步

    离线同步指源库已经脱线,不对外提供服务,这也意味着源库数据不会再发生变化。目前市面上的常见的开源同步工具基本都是面向离线同步,比如阿里的DataX。

    在线同步则正好相反,源库依然对应用层系统提供数据服务,我们需要在数据不断发生变化的情况下将变化数据同步到其他目的库。这里面的变化包括插入、更新、删除,甚至包括DDL操作(添加/删除字段、修改字段类型、Truncate操作等),每一类变化都不好处理。

    由此可见,在线同步比离线同步要复杂得多。

    ▪ 全量同步和增量同步

    全量同步很好理解,就是将当前可以看到的源表上的所有数据一次性全部同步到目的库表(源表数量可能非常大);而后针对变化的数据,再进行增量同步。

    ▪ 实时同步、近实时同步和非实时同步

    这是从实时性角度的划分,我们当然希望源库变化的数据越快同步到目的库越好。实时性在时间上并没有明确的定义,但一般我们认为基于binlog复制方式的同步是实时的(虽然大多数binlog复制方式是异步发生的)。

    对于我们的自研工具da-syncer,在事务量不大的情况下会在1分钟之内将Oracle主站数据同步到其他目的库,可以看做是近实时同步。

    非实时同步则对实时性没有太高要求,比如可以是T + 1。

    三、数据同步的痛点

    无论做何种数据库产品间的数据同步,我们都面临着一些普遍存在的痛点问题,这些痛点问题如果解决不好,会影响数据同步整体准确性和效果。

    下面罗列出一些本人遇到的问题,并提供相应解决方案供大家参考。

    (1)不同种类数据库字段的类型映射

    好的同步工具在做同步任务前会解析源表表结构,并依据源表表结构自动在目的库创建出目的表,然后才进行数据同步操作。

    那如何提取出源表的表结构呢?

    除了使用JDBC的Metadata接口外,其实更直接更准确的方式是查询源库的元信息表,比如对于Oracle:

    SELECT utc.column_id, utc.column_name, t_pk.position, utc.data_type, utc.data_length,

    utc.char_length, utc.data_precision, utc.data_scale, utc.nullable

    FROM user_tab_columns utc,

    (

    select ucc.column_name, ucc.position

    from user_constraints uc, user_cons_columns ucc

    where uc.table_name = ucc.table_name

    and uc.constraint_name = ucc.constraint_name

    and uc.constraint_type = 'P'

    and uc.table_name = ?

    ) t_pk

    where utc.table_name = ?

    and utc.column_name = t_pk.column_name(+)

    order by t_pk.position asc, utc.column_id asc;

    可以将表结构信息,如主键(包括联合主键),数据长度、精度、刻度、是否为null等信息一次性提取到位。对于MySQL也类似,可以从information_schema.columns元信息表提取,这里不再赘述。

    如果在同种类数据库间同步数据,则使用上述提取的源表表结构信息直接在目的表建表即可;如果我们需要在不同数据库产品间做数据同步时,则接下来需要知道它们之间字段类型的映射关系,以解决类似Oracle的Number对应MySQL什么数据类型的问题。

    通过查阅Oracle官方文档,可以获取这种映射关:https://docs.oracle.com/cd/E12151_01/doc.150/e12155/oracle_mysql_compared.htm#g1034154

    (2)主键要求

    数据同步对源表上主键的存在性是有要求的,这是因为源表上的每条记录都应该有一个“身份”。尤其在增量同步中,当源表记录发生变化时,我们需要依据这些发生变化的源表记录的“身份”去目的表查找,如果找不到记录就进行插入操作,否则就进行更新操作。

    如果同步源是MySQL,则我们可以强制必须存在主键才能进行同步操作,这是因为主键如果不存在,查找会退化成表的全字段匹配,效率非常低下。如果同步源是Oracle,则可以不存在主键,因为我们可以使用Oracle的伪列rowid作为主键。

    (3)源表记录获取:游标

    在目的表创建完和源表对应的表结构后,我们就可以从源表拉取数据,插入到目的表。

    通常情况下我们在应用层程序中进行数据库查询操作,比如在MyBatis中,可以直接使用Mapper注解的方式(@SelectProvider注解),或者将我们的SQL登记在xml中(元素),查询的结果有可能是一个List列表。

    默认情况下,上述MyBatis使用的是客户端游标方式(Client Side Cursor),其运行原理是将符合查询条件的记录一次性全部load到客户端虚拟机中形成一个记录集(resultset),在该记录集之上再进行游标的移动。

    但是源表记录数有可能非常大(1000万+甚至更多),在做全量同步时需要把全表数据提取出来插入到目的表。这很容易发生OOM内存溢出错误。为了避免该问题发生,我们应该启用服务器端游标(Server Side Cursor):

    ▪ 如果同步源是MySQL,需要在JDBC URL中添加useCursorFetch=true参数;Oracle则不需要。

    ▪ 在代码层面同样需要设置(可以在Statement级或更细粒度的ResultSet级):

    PreparedStatement ps = conn.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);

    ps.setFetchSize(500); //可以根据业务情况调整fetch size大小

    ps.setFetchDirection(ResultSet.FETCH_FORWARD);

    服务器端游标的原理在于我们查询执行完毕后,会在数据库服务器端形成一个只跟当前客户端连接关联的结果集(或者说是记录集快照),客户端可以批量随需从数据库服务器端抓取记录到本地进行处理,而非上述的一次性抓取行为。

    这里面有一个坑需要注意一下,对于使用服务器端游标形成的JDBC ResultSet结果集对象,如果结果集中还有记录没有抓取完毕,则关闭该ResultSet对象会出错。

    (4)源表分段处理

    你可能认为我们在使用服务器端游标后,从源表抓取记录到本地再一步步处理即可。但事实上远非那么简单,其中最重要的一个问题是,服务器端为你生成的记录集快照(Snapshot)并非是永久性的。

    比如在Oracle中,为了维持这个快照的数据一致性,需要很多的undo表空间(undo tablespace),尤其是查询大表形成的快照,而该空间通常是多事务共享循环使用的,如果有其他大量事务提交,你的数据很有可能在空间中被覆盖,形成下列错误:

    ORA-01555: snapshot too old: rollback segmeng number xxx with name xxx too small

    在不依赖于数据库配置的前提下,我们必须在应用层采取必要措施来防止这个问题,我们的解决思路是依据源表主键对源表进行分段,然后再基于分段进行查询处理,以减少出现该问题的几率。

    目前da-syncer工具仅仅实现了对Oracle/MySQL源表存在单个主键的大表进行分段。假设大表t1表的主键字段是id,对于Oracle来说,关键的分段语句是:

    select max(id) from(select id from t1 where id >= ? order by id asc) where rownum <= ?

    对于MySQL来说,关键分段语句是:

    select max(id) from (

    select @rownum:=@rownum+1 as rn, id

    from (select @rownum:=0) r, t1

    where id >= ?

    order by id asc

    ) t where rn <= ?

    在上述SQL执行时,需要注意的是应该传入和主键类型匹配的JDBC参数类型值,比如,如果主键是char/varchar类型,则应该传入字符串,如果是长整型,则应该传入BigDecimal或Long,否则分段SQL进行主键值比对时将走全表扫描。

    举个例子来讲,对于Oracle,如果大表t1上没有主键,则完全可以使用rowid伪列作为主键字段进行分段,但其实rowid伪列的字段类型是ROWID,很多同学喜欢直接where rowid = 'AAAvR2AAUAABsgEAAX'把rowid字段跟字符串比较,这样的查询操作会走全表扫描,效率非常低下,应该使用chartorowid函数进行转换。

    上面讲到da-syncer工具只针对具有单个主键的大表进行了分段处理,目前处理的最大的一张表的记录将近4个亿,500万一个分段,分成了80个分段进行处理。

    那如果大表是联合主键该怎么分段呢?这个问题可以留给大家思考。

    (5)提升同步性能

    为了尽快地将数据从源表同步到目的表,以提升同步性能,我们可以考虑以下几个方面:

    ▪ 查询源表时明确指定按主键排序

    我们可能已经注意到,当执行select * from t查询时,无论表上加多少索引,结果集通常是按主键升序排列好的。

    这是因为每张数据库表都有一个聚簇索引(假设MySQL使用InnoDB存储引擎),表数据文件本身就是按B+树组织的一个索引结构,这个索引的key是数据表的主键,这棵树的叶节点保存了完整的表记录数据。换句话说,主键值顺序决定了表数据行的真实物理存储顺序。

    为了防止源表一些查询可能会打乱主键顺序,如果明确指定按主键排序,并以此顺序插入目的表,则会最大程度地抑制目的表数据文件为了维持B+树的特性而进行的频繁的移动、分裂、旋转、调整,从而降低物理I/O成本。

    ▪ 批量插入/更新/删除

    批量操作也是提高性能的利器,JDBC在Statement/PreparedStatement上提供了batch操作的方法。在此不再赘述。

    注意:对于MySQL数据库,需要在JDBC URL中添加rewriteBatchedStatements=true参数才能使batch工作正常,这样batch insert会使用“insert into t (…) values (…), (…), (…)”这样的SQL结构,而batch update/delete也会组合后一次性发往服务器端执行。

    另外,通常数据库对一次SQL提交的数据包大小也有限制,比如在MySQL中,可以查询max_allowed_packet参数的使用。

    ▪ 最后提交

    我们不必每批次插入/更新目的表后就commit使数据生效,可以最后commit一次即可。

    (6)增量数据判断:不靠谱的last_modified_date字段

    通常情况下,为了判断增量数据,我们会在源表中添加一个“last_modified_date”或类似的字段然后再加上索引,比如在MySQL中:

    alter table t1 add column last_modified_date timestamp not null default current_timestamp on update current_timestamp;

    当源表数据发生更改时(如发生insert/update操作),记录的last_modified_date会自动发生改变,我们可以把所有last_modified_date大于上次增量同步时间的记录查询出来做同步处理。

    这是一个常规做法,但是这个做法是有问题的,其根本原因在于last_modified_date反映了事务的操作时间(什么时候执行的插入/更新操作),而非生效时间(事务commit时间),这两个时间间隔可以相差很久。

    举个简单的例子来说明,打开第1个MySQL客户端进行一系列操作(见图1):

    1.创建test表

    2.开启一个事务

    3.插入一条name是name1的记录

    4.查询

    5.休息10秒钟

    6.再次查询

    注意,此时事务尚未提交。可以发现4.和6.的查询中last_modified_date值是一样的,它反映了3.中插入这条记录时的操作时间。

    3b50b15f8cb92a6cc19ac28ac1bceb1f.png

    图1:第1个MySQL客户端操作演示

    打开第2个MySQL客户端进行一系列操作(见图2):

    1.查询,因为默认隔离级别是repeatable read,所以看不到客户端1上的未提交记录

    2.插入4条新记录

    3.查询,只能查询到当前客户端提交的4条新纪录

    d9db2bae7db23686fd2bccd3043e3200.png

    图2:第2个MySQL客户端操作演示

    假设此时开始做全量同步,则只有客户端2上的4条记录被同步到目的表,再求max(last_modified_date)发现记录5的值最大,将其保存作为下次增量同步的起始值(也就是last_modified_date大于这个值的记录认为发生过变动,需要增量同步)。

    将客户端1上的事务提交,这时候客户端2上也会看到这条提交的记录,且记录1的last_modified_date始终未改变(见图3):

    04fb2be76a3ecf12fcfd3f5cff8770d5.png

    图3:客户端1提交后在客户端2上查询

    当我们开始增量同步,查询last_modified_date大于记录5的last_modified_date的那些记录时,找不到任何东西,记录1被永远遗弃不能同步了。

    所以,last_modified_date字段用于增量同步判断的字段,并不靠谱,但是又不得不使用。在da-syncer工具中,我们会把last_modified_date的时间提前一定时间,比如10分钟,在很大程度上减少了出问题的几率,但是并不能从根本上解决问题。

    对于Oracle来说,除了last_modified_date,还可以使用更靠谱的ora_rowscn伪列,它是一个长整型数,反映了事务真正的提交时间,所以可以放心使用。

    只不过有一个问题,如果在创建Oracle表时未指定rowdependencies,则默认ora_rowscn伪列是基于Oracle块的,这意味着,即使只插入/更新/删除一条记录,位于同块上的其他记录的ora_rowscn也会变化,这会造成成百上千条无效记录被查询出来同步到目的表,既浪费了服务器资源,又浪费了网络带宽。

    在本系列文章的第二部分时序性保障中,我们将介绍如何使用Oracle的闪回版本查询(flashback version query)来避免这个问题。

    使用ora_rowscn的第二个问题是不能用到索引,这是一个蛋疼的问题,除非像Linkedin的Databus那样在源表上添加trigger,将ora_rowscn存入其他用户表,再自己建索引。

    (7)插入还是更新,这是一个问题

    假设我们已经通过last_modified_date或ora_rowscn机制从源表查询出此次增量同步中发生变化的记录,该如何把它们同步到目的表呢?

    这些记录发生变化的原因有两种,一种是原来不存在是新插入的,对于这种记录我们应该插入目的表;另外一种就是发生了更改操作,此时我们应该依据主键信息从目的表找到匹配的记录进行更新操作。所以,对于每一条变化的记录,都有一次在目的表中查询记录存不存在的操作,然后再决定是插入还是更新。

    幸好目前的数据库可以提供native的SQL把两步合并成一个SQL,如在MySQL中:

    insert into … on duplicate key update …;

    对于Oracle,有:

    merge into … using … when matched then … when not matched then …

    (8)数据比对:源表有物理删除怎么办

    无论是基于last_modified_date还是ora_rowscn伪列,都不能检测到那些在源表被物理删除的记录。此时,我们必须有独立线程定时查询目的表记录,通过批量从目的表抓取主键列表,然后看看这些主键列表在源表存不存在,如果不存在就在目的表中删除,从而保持两边记录的一致性。

    (9)恼人的编码问题:collation和utf8mb4

    不同的数据库产品支持不同的字符集和编码。在Oracle中,字符串是区分大小写的,而在MySQL中,默认是不区分的,可以使用如下SQL进行测试:

    select 1 from dual where 'a' = 'A';

    当我们将数据从Oracle同步到MySQL,为了业务理解上的一致性,我们需要维持这种语义上的连续性,此时,必须在库级别或者表级别设置collation为binary模式,比如utf8_bin。

    同时,为了支持emoj表情符,我们需要把MySQL字符集设置为utf8mb4,否则会显示乱码。

    以上挑选了几个在数据同步中需要特别注意的点进行介绍,实际上还有其他一些小问题,比如不同数据库有不同的关键字字典,当这些关键字作为表名或字段名的时候必须进行转义处理等等,都是细节性的,就不再赘述了。

    在下一部分,我们将带你进入 :

    “深入数据库同步技术(2)- 时序性保障”

    12

    责任编辑:

    展开全文
  • JAVA线程同步技术

    2020-12-24 12:49:42
    1、同步技术分类 1.1 关键字 ● synchronized ● volatile 1.2 类方法 ● Object: wait、notify、notifyAll ● Thread: sleep、join、yield 2、synchronized monitor:分为对象监视器和类监视器,不同类型监视器加锁...

    1、同步技术分类
    1.1 关键字

    • synchronized
    • volatile

    1.2 类方法

    • Object: wait、notify、notifyAll
    • Thread: sleep、join、yield

    2、synchronized
    monitor:分为对象监视器和类监视器,不同类型监视器加锁互不影响
    作用域:方法体,代码块
    用于方法之上,对该实例对象或类的monitor加锁

    public synchronized [static] void fun(...)
    

    用于代码块,对实例对象或类的monitor加锁

    public void fun(...) {
     synchronized(obj) { // synchronized(this) or synchronized(class)
     ...
     }
    }
    

    竞争monitor举例

    • 线程各自获取monitor,不会有等待
      synchronized(class) //对类的monitor加锁
      synchronized(this) //对对象的monitor加锁

    • 如果不同线程监视同一个实例对象就会等待,如果是不同的实例则不会等待
      synchronized(this) //对对象的monitor加锁
      synchronized(this) //对对象的monitor加锁

    • 如果不同线程监视同一个类就会等待,如果是不同的类则不会等待
      synchronized(class) //对类的monitor加锁
      synchronized(class) //对类的monitor加锁

    3、volatile
    轻量级同步机制,主内存(main memory),工作内存(cpu cache),可见性,原子性

    在开始讨论类方法线程同步之前,我们再次回顾下线程状态

    4、JAVA线程状态
    ● 新建状态(New)
    新创建了一个线程对象。

    ● 就绪状态(Runnable)
    线程对象创建后,其他线程调用了该对象的start()方法。该状态的线程位于“可运行线程池”中, 只需等待获取CPU的使用权 ,即在就绪状态的线程除CPU之外,其它运行所需资源都已全部获得。

    ● 运行状态(Running)
    就绪状态的线程获取了CPU。

    ● 阻塞状态(Blocked)
    阻塞状态是线程因为某种原因放弃CPU使用权暂停运行,直到线程进入就绪状态,才有机会转到运行状态。 阻塞的情况分三种:

    • 等待阻塞
      运行的线程执行wait()方法后,该线程会 释放占用的所有资源 ,JVM会把该线程放入“等待池”中。进入这个状态后不能自动唤醒,必须依靠其他线程 调用notify()或notifyAll()方法才能被唤醒 。

    • 同步阻塞
      运行的线程在获取对象的同步锁时,若该 同步锁被别的线程占用 ,则JVM会把该线程放入“锁池”中。

    • 其他阻塞
      运行的线程执行sleep()或join()方法,或者发出了I/O请求时,JVM会把该线程置为阻塞状态。当sleep()状态超时、join()等待的线程终止或超时、I/O处理完毕时,线程重新转入就绪状态。

    ● 死亡状态(Dead)
    线程执行完或者因异常退出了run()方法,该线程结束生命周期。

    5、类方法
    5.1 Object类

    • wait
      调用wait方法会让当前线程 放弃该对象的对象锁 ,并进入对象锁的等待锁定池,直到被notify或notifyAll唤醒继续执行,或者被中断; 调用前提是需要先获得该对象锁 ,因此需要将wait调用置于同步块synchronized(obj)之内。

    • notify / notifyAll
      notify-随机唤醒一个等待的线程,notifyAll-唤醒全部等待的线程; 调用notify()后,并不会立即释放锁,而是继续执行当前代码,直到synchronized中的代码全部执行完毕; notify有两个问题:一是唤醒的线程当前不一定需要获得该锁,二是可能造成死锁。 例子:三个人吃苹果,一个削两个吃。 注意:wait/notify/notifyAll都必须放在synchronized方法或块中执行 ,否则会抛IllegalMonitorStateException 异常.

    5.2 Thread类

    • sleep
      当线程调用了自身的sleep()方法或其他线程的join()方法,进程 让出CPU ,然后就会进入阻塞状态(该状态停止当前线程,但并不释放所占有的资源,即调用sleep ()后,线程 不会释放“同步锁”)。 当sleep()或join()结束后,该线程进入可运行状态,继续等待OS分配CPU时间片。

    • join
      把指定的线程加入到当前线程,直到指定线程执行结束或者等待一定时间后,才继续往下执行。 原理:调用指定线程的wait方法释放monitor。

    • yield
      放弃当前获得的CPU时间片,回到就绪状态,执行yield()的线程有可能在进入到可执行状态后马上又被执行。

    sleep与wait 比较

    • 异:sheep不会释放对象的同步锁,而wait会;
    • 同:两者都支持中断,即在sleep与wait期间,都可以通过interrupt调用让它们立即抛出InterruptedException异常。
      public static native void sleep(long millis) throws InterruptedException;
      public final native void wait(long timeout) throws InterruptedException;

    6、线程同步工具
    6.1 Concurrent包

    • Semaphore
      计数信号量,功能是限制同时获得许可的数量,通过阻塞(acquire)、释放(release)来管理许可的发放与回收。

    • ReentrantLock
      可重入的互斥锁,与synchronized有相同的并发性和内存语义,但功能更强大。

    • BlockingQueue
      阻塞队列,提供了阻塞接口put和take,分别在队列为满和为空时自行阻塞,直到满足要求后继续执行,其实现依赖ReentrantLock。

    • CountDownLatch
      倒记数锁,使一个线程在一组线程未全部执行完之前一直等待,直到计数到达0。计数只能减不能增,也不能重置,如果需要重置,可考虑用CyclicBarrier代替。

    • CyclicBarrier
      循环壁垒/屏障,允许一组线程在到达某个公共屏障点之前互相等待,可多次使用。

    6.2 Atomic包:

    • AtomicInteger
      一个线程安全的整数封装类,可以在并发情况下安全的设置/获取对象的值。 源码分析

    6.3 Lock(ReentrantLock)与Synchronized比较

    • 同:ReentrantLock 与synchronized有相同的并发性和内存语义
    • 异:synchronized是在JVM层面实现的,而ReentrantLock使用代码实现。
      synchronized机制强制所有锁获取和释放均要出现在一个块结构中,当获取了多个锁时,它们必须以相反的顺序释放,只要线程运行的代码超出了synchronized语句块范围,锁就会被释放。而ReentrantLock对锁的占有和释放是显示的,使用稍显复杂相比synchronized但更加灵活。

    使用建议:在并发量比较小的情况下,使用synchronized是个不错的选择,但是在并发量比较高的情况下,其性能下降很严重,此时ReentrantLock是个不错的方案。

    7、线程同步应用:生产者-消费者模型

    • 实现一、synchronized + Object.wait/notifyAll
    • 实现二、ReentrantLock.Condition
    • 实现三、BlockingQueue

    8、术语

    • monitor
      监视锁,同步锁,每个java对象和类在逻辑上都有唯一的一个monitor,任何时候都最多只能有一个线程占用这个同步锁;释放方法:wait。

    • 可见性
      是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改的结果。另一个线程马上就能看到。

    • CAS
      Unsafe类的compareAndSwapxxx方法。

    • 互斥锁
      所谓互斥锁, 指的是一次最多只能有一个线程持有的锁,过程中有上下文的切换,cpu的抢占,信号的发送等开销。

    • 自旋锁
      线程一直处于运行中,死循环检测锁的标志位。自旋锁是一种非阻塞锁,如果某线程需要获取自旋锁,但该锁已经被其他线程占用时,该线程不会被挂起,而是在不断的消耗CPU的时间,不停的试图获取自旋锁直到获得。

    9、参考资料:

    • http://blog.csdn.net/wulei_longhe/article/details/30032031
    • http://blog.csdn.net/zolalad/article/details/38903179
    • http://blog.csdn.net/monkey_d_meng/article/details/6251879
    展开全文
  • 时钟同步产品(时间同步系统)技术应用方案 分布式系统由Tanenbaum定义,“分布式系统是一组独立的计算机,在”分布式系统 — 原理和范例“中作为用户的单一,连贯的系统出现”。 区块链通过构建全球分布式系统,...

    时钟同步产品(时间同步系统)技术应用方案

    分布式系统由Tanenbaum定义,“分布式系统是一组独立的计算机,在”分布式系统 — 原理和范例“中作为用户的单一,连贯的系统出现”。

    区块链通过构建全球分布式系统,尝试实现分散的新数据存储和组织结构。

    首先,定位到分布式系统的原因主要是可扩展性,位置和可用性。区块链也不例外。地理可扩展性,形成全球价值存储网络/信息保护区域,包括非集中式结构下的防篡改/零停机时间的可用性。这些未来都是使用分布式系统在block中实现的。

    0.目录

    X.区块链和分布式系统

    1.简介(同步和整体流程概述)

    2.时钟同步

    2–1。物理时钟(时钟和时钟偏移)

    2–2。 时钟同步算法(网络时间协议(NTP)/伯克利算法)

    3.逻辑时钟

    3–1。 Lamport的逻辑时钟(完全有序的多播)

    3–2。 矢量时钟(因果订单组播)

    4.独家控制

    4–1。 集中算法

    4–2。 分散算法

    4–3。 分布式算法

    5.选举算法

    5–1。 欺负算法

    5–2。 环算法

    6.阻止链和同步作为分布式系统

    6–1。 块链和时钟同步(块链和物理/逻辑时钟)

    6–2。 块链和独占控制算法(PoW·PoS·BFT中的独占控制算法)

    6–3。 块链和领导者选举算法(PoW·PoS·BFT中的领导者选择算法)

    1.简介(同步和整体流程概述)

    与集中式系统不同,在分布式系统中就时间达成一致并不容易。

    在前一种情况下,可以基于全局共享时钟确定绝对顺序关系,但是在后一种情况下,由于存在时钟值错误和对应时间,因此难以共享绝对时间。

    但是,绝对时间的顺序并不是绝对必要的,如果相对顺序是固定的,通常就足够了。

    在本文中,将按以下顺序解释节点之间的同步。

    时钟同步是如何发生的?

    使用逻辑时钟和矢量时钟的相对排序方法

    关于分布式系统一致性的排除控制算法

    关于分布式系统中的领导选举算法

    2.时钟同步

    2–1. 物理时钟

    时钟和时钟歪斜

    大多数计算机都有保持时间的电路,这种设备称为“时钟”。这是基于频率的振动,该振动可以通过晶体类型,切割方法和向精确加工的石英增加张力时的压力大小明确定义。

    虽然这个频率相当稳定,但不能保证不同计算机的所有晶体都能以完全相同的频率运行。由此引起的同步时间的差异称为时钟偏差。

    在这种情况下,特别是在实时系统中,如何使多个时钟与现实时钟同步以及如何同步时钟是一个问题。

    现实世界中的时间最初基于平均太阳秒,但现在铯133过渡9,192,631,770次的时间定义为1秒,并且定义了国际原子时间和通用协调时间(UTC)。为了向需要准确时间的人提供UTC,使用WWV并且时间以±10毫秒的精度提供。

    2–2. 时钟同步算法

    但是,大多数机器没有WWV接收器。因此,每台机器都需要时间跟踪和管理算法,以便所有机器都可以同步时间。

    顺便提及,用于确定是否需要重新同步的错误,即时钟偏移,如下测量。

    将H定义为每台机器计数的晶体振动引起的每秒中断次数(刻度数),并将C表示为该时钟的值。设Cp(t)表示机器的时钟值,当UTC时间为t时。

    如果将p定义为定义允许的时钟偏差量的最大漂移率,则假定它在以下范围内运行。

    1-p 《= dC/dt 《= 1+p

    也就是说,在从先前同步开始经过At秒之后,两个时钟最多分开2pΔt。

    当保证在操作执行时没有大于&的偏差时,必须至少每&/2p重新同步软件。

    网络时间协议(NTP)

    在许多协议中很常见,[Cristian,1989]首先提出的方法是一种与客户服务器通信的方法。由于时间服务器具有WWV接收器或具有准确的时钟,因此它可以提供当前时间。在与服务器通信时,重要的是延迟报告消息传播延迟的时间,但是通过估计延迟,这里可以最小化错误。目前,已知NTP能够在1至50毫秒的范围内实现精度。

    伯克利算法

    在诸如NTP的许多算法中,时间服务器是被动的并且仅回答查询。另一方面,在Berkeley算法中,时间服务器接收每个参与节点所持有的时间,并且还基于平均值改变其自己的时间。当时间值不必与现实世界有关系时,很容易在同一当前时间达成一致,并且它对此算法有效。

    3.逻辑时钟

    到目前为止,虽然我们描述了一种根据实际时钟将时钟与绝对时间同步作为参考的方法,但通常只执行相对同步。这里,逻辑时钟的概念用于确定相对顺序。

    3–1. Lamport的逻辑时钟

    为了同步逻辑时钟,Lamport定义了一个名为happen-before的关系。表达式a→b表示“a发生在b之前”,这意味着事件首先发生,然后所有进程都同意事件b将发生。发生之前 — 可以在以下两种情况下直接观察到关系。

    如果a和b是同一过程中的事件且a出现在b之前,则a→b为真。

    1. 如果a是由一个进程发送的消息的事件,并且b是由另一个进程接收的该消息的事件,那么a→b也是如此。在发送消息之前无法接收消息,即使消息同时也需要有限的非零时间。

    因为发生前关系处于过渡关系中,如果a→b和b→c,则可以证明a→c。如果事件x,y出现在不交换消息的不同进程中,则x→y和y→x都不为真,并且这些事件被认为是并发的。 (之前发生的关系未知。)

    利用逻辑时钟,通过分配所有进程对每个事件a一致的时间C(a)来测量相对时间。如果这些时间值是a→b,则通过向时间添加正值来校正它们,使得C(a)《C(b)。通过分配如下图所示的时间值,可以掌握之前发生的关系。

    在Lamport的逻辑时钟中,如果a→b,则可以证明C(a)《C(b),但如果C(a)《C(b)则a→b不一定成立。换句话说,a→b是C(a)《C(b)的必要条件,并且不是充分条件。 Lamport的逻辑时钟增加了改进,它是一个矢量时钟,可以满足这种必要和充足的条件。

    完全有序的多播

    有关详细信息,请参阅“分布式系统一致性”一文中的内容

    在许多情况下,有必要在重复的副本之间执行完全有序的多播。换句话说,所有消息都需要以相同的顺序传递给每个收件人。 Lamport的逻辑时钟可用于在完全分布式系统下实现完全有序的多播。

    当进程收到某个消息时,它会根据时间戳按顺序放入本地队列。收件人向另一个进程多播确认。如果您按照Lamport的算法调整本地时钟,则所有进程实际上都具有本地队列的相同副本。只有当消息位于队列的头部并且被所有其他进程确认时,才有一个进程可以将队列中的消息传递给正在运行的应用程序,因此,所有消息都以相同的顺序传递到各处。换句话说,已经建立了完全有序的多播。

    3–2. 矢量时钟

    使用矢量时钟,可以掌握Lamport逻辑时钟无法掌握的因果关系。 假设事件a的向量时钟是VC(a),则执行以下步骤,使得a→b成为VC(a)《VC(b)的必要和充分条件。

    在通过网络发送消息之前,节点Pi向矢量时钟VCi [i]添加1,或者操作一些内部事件。

    1. 如果处理Pi将消息m发送到Pj,则Pi在执行前一步骤之后将m的向量时间戳ts(m)设置为等于VCi。

    2. 当接收到消息m时,进程Pj执行步骤1,将消息分发给应用程序,然后更新其自己的向量时钟的每个k,如下所示:VCj [k]←max {VCj [k],ts(m)[k]}。

    因果关系多播

    通过使用向量时钟,可以实现稍微弱于上述完全有序多播的因果有序多播。

    通过比较矢量时钟的值并掌握发生在之前的关系,对于特定事件x,其他事件可以被分类为过去事件,并发事件和未来事件。例如,在上图中,当事件d用作参考点时,过去事件是a,b,c,i,并发事件是j,l,m,未来事件是f,g,h。

    此时,假设因果有序多播是过去事件和因果事件的序列,其中发生所有因果关系,以便在所有过程中保持一致,但是关于并发事件的顺序是无关紧要的。通过这种方式,与Lamport的逻辑时钟不同,可以用向量时钟来掌握因果关系。

    4.独家控制

    多个进程之间的并发操作和协作操作是分布式系统的基本,但是为了保证对资源的独占访问,以便通过多个进程同时访问相同资源时不处于不一致状态时,需要分布式排他算法。

    分布式独占控制算法可以分为以下两种类型。

    基于Token的解决方案

    基于权限的方法

    在基于Token的方案中,很容易避免StarvaTIon(很长时间内不允许访问资源)和死锁(多个进程等待彼此的进展)。一个代表性的例子是Token环算法。但是,当持有Token的过程异常停止并且Token丢失,有必要只生成一个新Token,这种复杂性是一个严重的缺点。

    许多其他分散的独占控制算法采用基于权限的方法,并有许多不同的获取权限的方法,我们将分别具体解释。

    4–1. 集中算法

    通过模拟单处理器系统的功能,可以轻松实现分布式系统中独占控制的单一访问。在集中式算法中,一个进程被指定为协调器,并且当进程访问共享资源时,请求消息被发送到协调器以获得许可。如果其他进程未访问共享资源,则协调器返回权限响应,并且在接收到回复之后,所请求的进程执行该进程。

    很容易看出,该算法保证了对资源的独占访问,但它具有单点故障的严重缺点。虽然这可能是大型系统中的性能瓶颈,但这种简单性带来的优势仍然可以弥补这些缺点。

    4–2. 分散算法

    假设各项都会重复n次。在分散算法中,当进程访问资源时,需要批准大多数m》 n / 2。如果获得大多数批准,则该过程获得许可并可以进行处理。

    虽然该方案解决了集中式算法的单点故障问题,但是如果有太多的节点试图访问,则存在另一个问题,即没有节点可以获得足够的投票而无法获得充分的性能。

    4–3. 分布式算法

    在该算法中,假设系统上所有事件的顺序可以定义为完全有序的关系。作为这个基础,使用了前一章中描述的Lamport的逻辑时钟,并且假设没有消息会丢失。

    当进程尝试访问共享资源时,它会创建一条消息,其中包含资源名称,自己的进程号和当前逻辑时钟,并将其发送给所有其他进程。当接收到该请求消息时,根据其自身状态执行以下操作。

    1. 如果收件人未访问该资源且未尝试访问该资源,则收件人会向发件人返回“确定”消息。

    2. 如果收件人已在访问资源,请不要回复并执行排队请求。

    3. 如果收件人正在尝试访问资源但尚未完成,请将输入消息中的时间戳与发送给其他进程的消息中的时间戳进行比较,并将较低的一个作为获胜者。如果收到的消息具有小的时间戳,则收件人返回OK消息。如果自己的消息具有较小的时间戳,则接收方将不会将输入消息排队。

    显然,如果它不像process1或2那样冲突,这个算法就能正常工作。即使在冲突的情况下,也只建立了唯一一个进程可以访问的条件。

    与集中式算法一样,该算法可以保证独占控制,不会出现死锁或饥饿。 此外,没有单点故障。 尽管如此,单点故障被故障n位置特征所取代。 它可以通过回复权限或拒绝权限并引入超时来解决,但也会出现其他问题,例如需要多播通信原语。 不幸的是,目前尚未设计出超越集中式算法的分布式算法,并且仍在研究中。

    当比较各个算法时,变为如下。

    5.领导者选举算法

    许多分布式算法需要一个特殊的过程,它具有领导者作为协调者或发起者的角色。哪个过程是领导者,唯一过程是否可以成为领导者是一个重要问题,研究人员在过去几十年中一直在努力。

    5–1. 欺负算法

    当协调员失败并且任何进程P注意到该情况时,P根据以下过程激活选举。

    · P向所有具有比其自身更高数值的进程发送ELECTION消息。

    · 如果没有人回复,P将赢得选举并成为协调员。

    · 如果来自具有高于P的数值的过程的答案,则将替换它。 P的工作结束了。

    使用该算法,可以唯一地确定协调器。但是,该算法需要大量的消息和数据流量,可以说是冗余的。作为替代方案,存在环算法。

    5–2. 环算法

    与一般环算法不同,该算法不使用Token。发现协调器不工作的任何进程构造一个包含其自己的进程号的ELECTION消息,并将该消息发送给其后继者(环网中的下一个节点)。如果继任者失败,请跳过。如果没有比您更高的数值的节点,您的消息将仍然返回给您自己的进程号,因此它将被指定为协调员。

    在该算法中,执行具有减少数量的消息的领导者选举,但是还可以通过将消息的目的地设置到两个相邻节点来实现具有较少量数据流量的算法。

    6.阻止链和同步作为分布式系统

    因此,在作为分布式系统之一的块链中,进程之间的同步如何发生?

    6–1. 区块链和时钟同步

    块链和逻辑时钟

    首先,考虑是否可以使用区块链中的物理时钟来掌握绝对时间关系。如第2章所述,参与网络的每个节点并不总是保持正确的物理时钟,并且应该存在时钟偏差。由于比特币区块链的平均生成时间是10分钟,因此认为即使一定程度的大时钟偏差也是可接受的。然而,当节点散布在世界各地时难以同步各个物理时钟,并且还可能存在伪装时钟的节点。通过引入网络时间协议(NTP)来重新同步节点之间的正确时间是一项困难的技术。

    区块链和逻辑时钟

    因此,准备逻辑时钟而不是物理时钟是切合实际的。实际上,通过在块中加入时间标记,可以制备出与Lamport逻辑时钟非常相似的机制。

    如[比特币:点对点电子现金系统Satoshi Nakamoto]中所述,对作为矿工的区块执行写操作的每个节点本身具有作为时间戳服务器的角色。每个时间戳通过在其哈希中包含前一个时间戳来形成链。但是,无法保证这些节点保持正确的物理时钟。时间戳的数值,即每个事务的顺序和时间相对模糊。

    由于时钟的这种模糊性,有可能会进行双重付款。但是,在比特币区块链中,只有最长的链是合法的,在次要验证后丢弃不正确的交易。因此,区块的顺序随着时间的流逝唯一确定。随着每个时间戳的增加,前一个时间戳被加强。

    总之,在区块链中的模糊时间戳下,事务的顺序一致性是不准确的。然而,利用链式连接的简单机制,每个交易的发生前关系随着时间的推移而建立。此外,还有一种激励结构,以便矿工转移到良好,交易不一致的顺序不会发生。

    可以说,实现类似于Lamport的逻辑时钟的时钟同步方法,因为事务之间的相对顺序关系,即发生在之前的关系变得更清楚。

    对于大多数交易,没有因果关系,因此如果您引入向量时钟并采用因果关系排序的概念,则可以极大地放松订单关系的约束。然而,在区块链中,由于结构本身默认共享所有块的顺序关系,所以保持总排序(相对于在一段时间之后的块)。

    6–2. 区块链和独占控制算法

    即使在作为分布式系统的区块链中,也需要排除控制。在区块链网络中,每个节点并行地异步操作。此时,要共享的区块链本身的信息不应该不一致。

    PoW·PoS中的独占控制算法

    如第4章所述,分布式排他控制算法可分为以下两种类型。

    · 基于Token的解决方案

    · 基于权限的解决方案

    PoW和PoS是基于权限的,其中,可以说它是类似于分布式算法的机制。那么,您什么时候获得访问资源的权限?是的,就在你找到一个随机数时。

    在PoW中,只有当找到在哈希值后跟0后跟n为0的随机数时,才可以执行有效的新块写操作。执行操作的矿工将其广播给所有矿工并分享。

    通常,当节点找到一个nonce并创建一个比他自己更早的块时,minor会同步该信息并移动以搜索下一个nonce值。这是因为如果您使用最长链被认为合法的规则搜索下一个nonce值,它们可以获得更多利润。尽管PoS优先为具有较大硬币持有量的人提供资源访问,但基本排除控制算法结构也类似于分布式算法。

    但是,严格来说,不执行排除控制。这是为了在公共时间内同步并形成共识10分钟,直到下一个区块为止。当两个或更多个节点同时找到随机数值时,写入操作以非独占状态执行。此时,由于只有最长的链被认为是合法的,因此区块链网络中的信息与时间的流逝保持一致。叉子发生的一个问题是因为没有执行严格的排他控制而且没有确认最终结果。

    BFT类型的独占控制算法

    另一方面,通过BFT类型,基于许可的分散算法执行排他控制。该算法解决了分叉和终结问题,这是PoW中与分布式算法类似的问题。

    在BFT类型中,只有一个名为Proposer,Orderer等的节点有权生成新区块。创建区块时,您可以从所有参与节点收集投票,获得超过2/3的同意,您才有权创建新块。此时,有必要同意超过2/3而不是多数的原因是处理拜占庭故障,有关此问题的详细信息在“分布式系统中的容错”一文中有所描述。

    在BFT类型算法中,与PoW等不同,只有一个节点可以获得对区块链的独占访问权限,因此不会立即确定fork和finality。但是,任何人都可以作为矿工参与网络的财产往往会丢失。

    6–3. 区块链和领导者选择算法

    PoW,PoS和领导者选择算法

    区块链上的领导者选择算法类似于独占控制算法的机制。在比特币中,用于选举领导者的算法,即,新创建块的节点是PoW。

    PoW允许添加一个块作为一个好的领导者,为比特币网络提供有计算复杂性和发现nonce的节点。每个成为领导者的矿工都会尝试为比特币网络做出贡献,因为更容易早期同步到首先发现现时的节点并开始搜索下一个块的现时值更有可能获得奖励。尽管存在链条完全由硬叉分支的问题,但是通过基于博弈论准备非常简单的激励结构,在块链网络中实现作为分布式系统的同步。

    在以太坊的情况下,由于块生成的时间很短,因此倾向于发生更多的分叉。关于这一点,通过采用unkle块的概念,我们实现了一种结构,即使产生不合法的链条也会给予一定的奖励。

    将来引入未来的PoS允许优先生成具有大硬币保持量的节点的块作为引导者。这是一种解决/改善PoW中必要电量变得巨大且易受51%攻击的问题的算法。这是一种基于博弈论的选举算法,如果一个节点持有大量硬币,就不会采取破坏网络等恶意行为。

    BFT和领导者选择算法

    BFT类型算法的问题在于如何选择将投票给块生成的领导者作为Proposer或Orderer。

    在PBFT采取的HyperLedger当中,原为可信赖的机构才会注册为Orderer。 但这是集中式的领导者选择方法,与分布式系统存在着明显的区别。

    在Tendermint协议当中,领导者以循环方式被选出,以通过与不同验证者的轮换交替来提出建议。 此时,领导候选者是基于PoS,并且可以说是可以在分布式系统中实现领导者选择的算法之一。

    展开全文
  • 储能虚拟同步技术

    千次阅读 2021-03-22 09:33:22
    储能虚拟同步技术 上一、背景和基本原理二、作用与接入方案 一、背景和基本原理 虚拟同步机(Virtual Synchronous Generator,VSG)可以通过在变换器控制环节中模拟同步机运行机制,使新能源发电设备具备主动支撑...

    一、背景和基本原理

    虚拟同步机(Virtual Synchronous Generator,VSG)可以通过在变换器控制环节中模拟同步机运行机制,使新能源发电设备具备主动支撑电网的能力,由被动调节转为主动支撑。
    传统电力系统中大量采用同步发电机作为并网发电单元,同步发电机具有良好的惯性和阻尼特性,在增加调频调压装置后,能够参与电网频率和电压调节。而分布式发电需要通过电力电子变流器与外部电网连接,电力电子变流器具有动态响应速度快、过载能力低、谐波含量高等特点,若能将传统电力系统中同步发电机的模型结构引入电力电子变流器控制,模拟同步发电机运行特性,使电力电子变流器能够友好接入电网,有效避免对电网动静态稳定性产生不利影响,解决分布式发电并网或独立带载所面临的诸多问题。
    实际同步发电机中,频率和电压控制对电力系统稳定性影响极为重要。同步发电机是一个机械能量与电磁能量的转换装置,系统中有功功率变化时,其输入的机械能量与输出的电磁能量之间产生差异,引起同步机端口转速变化,进而引起电网频率的波动;系统无功功率变化时,由于同步电机转子的电气特性,端口输出电压也会出现相应变化,同步电机励磁调节器据此调整励磁电流,改变空载电动势,抵消转子电枢在无功影响下的电压波动,维持同步电机端电压近似保持恒定。如果VSG直流侧包含一定储能能量,当VSG参与一次调频时,就可通过储能装置吸收或发出虚拟转子动能,模拟类似同步发电机一样的惯性,并可参与电网一次调频控制。由于同步发电机热能-机械能-电能转换过程缓慢,而电力电子控制响应速度远快于同步发电机,固可用其实现更快的控制过程,进一步提高在电力系统中的应用范围。图1为VSG与同步发电机的对比。
    在这里插入图片描述图1 VSG与同步发电机对比图

    按照并网状态划分,VSG可以运行在并网和孤岛两种模式。并网运行时,能量可以进行双向流动,VSG可参与电网调节;孤岛运行时,VSG又能够为自身负荷供电。按照并联状态划分,VSG又分为单机模式和多机模式。单机模式时,VSG仅需要保证自身输出电压恒定;多机模式时,多台VSG之间需要进行相应功率分配。总体来看,VSG运行状态既取决于电网状态,也与其他VSG运行模式相关,同时还要考虑负荷和储能影响。

    二、作用与接入方案

    储能在虚拟同步机的应用主要体现在以下两个方面。
    (1)稳定电网
    储能可对VSG输出功率进行动态补偿,可再生能源的间歇性变化和负荷的随机性投切会造成VSG系统功率瞬态不匹配,通过储能模块及相应功率变换装置,可以快速平滑功率,提高电网电压和频率稳定性,其控制原理如图2所示。它的作用相当于传统电力系统中一次调频调压,而且储能装置还可实现电力系统低电压穿越,提高可再生能源接入时运行范围。
    域中间。
    在这里插入图片描述
    图2 储能参与电压频率稳定原理

    (2)多模式运行
    分布式电源一般在并网模式下启动,但当电网不存在或故障时,通过储能装置能够实现稳定可控的交流电压输出,并为内部负荷供电。同时,通过对分布式电源的电压和频率进行调控,能够实现在并网和离网之间随意切换。并网模式下,储能单元可实现自身能量优化管理,提高电网运行可靠性;独立运行时,通过储能装置出力能够保证负荷不断电的平稳运行,投切瞬间的能量偏差也可以通过储能装置进行吸收,基于储能的VSG多模式运行过程如图3所示。在这里插入图片描述
    图3 基于储能的多模式运行

    通常储能单元在VSG系统中有两种典型接入方案:集中式接入和分布式接入,如图4所示。
    在这里插入图片描述
    (a) 集中式接入
    在这里插入图片描述
    (b)分布式接入
    图4 储能接入方式
    集中式接入方式中,储能通常配置于VSG母线终端,在进行诸如电力调峰、短时供电、平抑功率波动、无缝投切等操作时,可将全部储能单元投入,对VSG系统整体调控作用较好。但这种方式在离网时完全依靠储能供电,需要具备较大容量的储能单元,储能本体和变换器系统设计的制造成本和难度较大。而且,当储能装置出现故障时,整个VSG系统都将失去可控功率源特性,鲁棒性较差,不利于系统扩容。
    分布式储能中,每一个可再生能源或用电负荷均包含一定储能单元,每个VSG均可实现功率流控制,能够避免某单元储能故障造成的整个系统性能变化,冗余度和可扩容性良好。但分散的储能装置以及变换器模块会大大增加VSG成本,而且为实现多个储能模块之间的能量管理,需要在各单元之间建立相应通讯连线,降低了系统可靠性。
    综合两种配置方式的特点,可根据VSG系统要求将集中接入和分布式接入结合。在直流母线侧配置较大容量的集中式储能,用于电力调峰、短时供电、并网孤岛投切缓冲等操作;在重要负荷和可再生能源附近配置一定分布式储能,用来平抑可再生能源功率波动,或为重要负荷瞬时出力,以较小容量得到更好的区域调节能力和供电可靠性。
    储能器件本身均为直流源,但绝大部分VSG端口为交流电网,因此VSG需要包含逆变单元和储能直流变换单元。根据储能直流变换类型,可大致分为以下几种结构。
    (1)无储能变换
    在这里插入图片描述
    图5 无储能变换

    图5为典型的无储能变换VSG拓扑结构,其中储能元件直接接于逆变器直流母线,充电时逆变器工作于整流状态,储能元件释放能量,放电时逆变器工作于逆变状态,储能元件吸收能量。该结构只包含一级逆变环节,结构简单易于控制,但对储能元件电压范围要求较为严格,适用于端口电压变化范围较小的蓄电池储能,同时为避免串联过多的蓄电池组,需采用体积庞大的工频变压器升压,成本较高。
    (2)储能DC/DC变换
    在这里插入图片描述
    图5 储能DC/DC变换

    图5中,储能元件经过DC/DC变换电路接于逆变器直流母线。该结构具有两类控制模式:一是前级DC/DC环节用于维持母线电压恒定,逆变环节则按照功率源形式向电网输出能量;二是逆变环节用于维持母线电压恒定,DC/DC环节则按照储能充放电要求控制储能单元能量比例。总体来看,采用两级结构有利于提高储能单元适用范围,控制方案选择灵活多变,但控制过程相对复杂。
    (3)储能AC/DC/AC变换
    在这里插入图片描述
    图6 储能AC/DC/AC变换
    图6为具备高频链的储能变换拓扑,通过DC/AC、高频变压器和AC/DC组成高频链回路实现储能元件电压变换,该结构体积小、重量轻、变换效率高。因其多级变换结构,交流侧和储能侧瞬时功率也可以解耦实现独立控制,但高频回路过载能力较差,多级结构控制也更复杂。
    根据VSG系统实际要求,既需要容量密度大的储能,也需要功率密度大的储能装置。受限于储能技术的发展,单一储能模块往往无法满足特定功率或者能量需求,目前多采用串并联、模块化扩展、多端口等手段进行扩容。

    展开全文
  • 同步整流SR

    千次阅读 2021-03-15 09:40:21
    同步整流1.杂谈2. 基本原理3. 分类 1.杂谈 3月份过去了一半,这个月一篇都还没开始,运动也不达标,实在是。。。 总觉得做这件事浪费时间,那件事浪费时间,到头来一件事没做好。知道自己哪不足还不去改正,还哭诉...
  • python 同步

    2020-12-18 13:37:30
    线程锁的使用 | 手把手教你入门Python之一百零二上一篇:线程安全 | 手把手教你入门Python之一...线程锁的使用同步当多个线程几乎同时修改某一个共享数据的时候,需要进行同...文章温柔的养猫人2020-07-11112浏览量p...
  • 2008 收稿日期: 20071217 作者简介:陶大伟 (19822) ,男 ,工程师 ,从事研究方向:计算机 运用 JAVA多线程技术仿真实现进程同步与互斥 陶大伟 (常州信息职业技术学院 江苏常州 213164) 摘 要 :针对高校操作系统这门...
  • l MobiLink同步技术 l 支持多种同步和网络协议 TCP/IP、HTTP、MS ActiveSync、Palm HotSync, ScoutSync、RiverBed Scout、支持无线同步。 l 可选用128位加密技术 13.3.4 MobiLink同步过程 图13-4 MobiLink同步过程 ...
  • 关注【冰河技术】微信公众号,第一时间阅读技术干货!!
  • 接口和抽象类的区别 五丶数据结构和设计模式 设计模式六大原则简要概述 设计模式的分类 3.HashMap 实现原理 六丶java核心小知识清单 1 .线程中 sleep 和 wait 区别 2.Thread 中的 start()和 run()的区别 3.Java 中...
  • 本发明涉及模式识别方法,特别是涉及一种AdaBoost算法中弱分类器的同步选取、加权、排序方法。背景技术分类算法就是基于分类器模型为待检测样本从可选的分类中选取最佳的类别假设,它属于人工智能中机器学习范畴,...
  • 一、 同步1、synchronized 关键字synchronized 锁什么?锁对象。可能锁对象包括: this, 临界资源对象,Class 类对象。1.1 同步方法synchronized T methodName(){}同步方法锁定的是当前对象。当多线程通过同一个...
  • 异步复制MySQL复制默认是异步复制,Master将事件写入binlog,提交事务,自身并不知道slave是否接收是否处理;...半同步复制当Master上开启半同步复制功能时,至少有一个slave开启其功能。当Master向sla...
  • 一种基于同步压缩变换重构的幅值校正方法【技术领域】[0001] 本发明属于信号处理技术领域,具体设及一种基于同步压缩变换重构的幅值校正 方法。【背景技术】[0002] 时频分析方法是处理非平稳信号的有力工具,目前...
  • 所以,要我请你吃饭就用同步的方法,要请我吃饭就用异步的方法,这样你可以省钱。--------------------------------------------------------------------------------------------------------------------举个例子...
  • 整合网络时间同步系统(NTP时钟同步设备)解决方案 整合网络时间同步系统(NTP时钟同步设备)解决方案 电力系统对统一时间的要求愈来愈迫切,高精度、可管理、高可靠的时间同步网已经成为现代化电力系统稳定运行的...
  • 而线程安全各个线程获得的实例变量的值都是经过同步处理的,不会出现脏读。1.线程是否安全呢?(1) 如果是方法内部的私有变量,不存在非线程安全问题。(2) 多线程访问的是同一个对象的实例变量时,有可能出现线程不...
  • 线程、同步

    2021-02-07 13:55:58
    格式: syncroized(同步锁){ ​ 需要同步操作的代码 } 同步锁: 对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁 1、锁对象可以是任意类型 2、多个线程对象要使用同一把锁 同步技术的原理: 使用了一个...
  • 【导读】为了帮助广大考生更好的备考,中公事业单位考试网提供2016年计算机专业知识《多媒体软件技术的概述及分类(一)》学习,为考生定制计算机基础知识复习计划。一、多媒体软件技术的概述多媒体技术使计算机具有...
  • 学习目标能够完成canal环境的搭建与数据监控微服务的开发能够...能够画出流程图和说出实现思路该工程使用lua+nginx+rabbitmq+redis等技术的第一个主要目的是实现轮播图的读取,具体图解:其中nginx的作用包括了从数...
  • 网络时间服务器(GPS北斗时钟同步)设备工作原理剖析 网络时间服务器(GPS北斗时钟同步)设备工作原理剖析 分布式系统由Tanenbaum定义,“分布式系统是一组独立的计算机,在”分布式系统 — 原理和范例“中作为...
  • 技术特征:1.一种基于html5网页的服务人员与客户之间针对方案的在线同步交流系统,其特征在于,所述系统包括:服务端,包括第一服务模块和第二服务模块;所述第一服务模块用于为第一客户端和第二客户端提供针对相同...
  • 前言这篇主要简单介绍 Java 集合库包含哪些常用的容器类,它们可以简单区分为:非同步集合同步集合并发集合那么,它们分别包括哪些具体的集合类,它们有什么主要的区别,以及它们的框架是怎样的?这就是今天要讲的...
  • 微软文件同步软件WindowsLiveSync详解分类:计算机等级|更新时间:2016-07-08|来源:转载Windows Live Sync Wave 4 是一款文件同步软件,与微软自家的Live Mesh相似,支持 PC(和 Mac)与云端间的同步、远程桌面控制。...
  • 基于MAT LAB/Simulink 的位同步电路仿真与分析郑惠群,高小雁,王成福(金华职业技术学院,浙江金华321000)摘要:同步在通信系统中占有非常重要的地位.锁相环在同步中用得很多,本文用基于MAT LAB 5.3的Simulink...
  • 前言 在 Java 中通过锁来控制多个线程对共享资源的访问,使用 Java 编程语言开发的朋友都知道,可以... 分类: Java 技术点: By © 2017 likecs 版权所有. 粤ICP备12038626号-2 Powered By WordPress . Theme by Luju
  • 新华网在《你知道无机盐对人体有多重要吗》一文中强调,无机盐在人体中具有重要作用,人体一旦缺乏不同种类的无机盐会产生相应的不同症状。  无机盐即无机化合物中的盐类,亦称矿物质。如钾、钠、钙、镁等。...
  • 一种多终端设备上的数据同步方法【技术领域】[0001] 属于移动通信技术领域,特别是涉及基于离网环境下多种移动终端设备之间的数 据同步的方法。 技术背景[0002] 90年代未,数据同步始于有线连接,如MAC机作为数据...
  • deadlock 中图分类号:TP312文献标识码:A文章编号:1006-4311(2010)07-0139-01 —— —— —— —— —— —— —— —— —— —— —— — 作者简介:赵元媛(1980-),女,山西汾阳人,工学硕士,讲师,主要...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 142,071
精华内容 56,828
关键字:

同步技术的分类