精华内容
下载资源
问答
  • 在液晶显示器中,行同步信号(HS)的作用是选择出液晶面板上有效行信号区间,场同步信号(VS)的作用是选择出液晶面板上有效场信号区间,行场同步信号的共同作用,可将选择出液晶面板上的有效视频信号区间。...
  • 但测试库里tt_student也需要更新,由于学生数量过于庞大,再重新导入的话费时费力,那么数据同步起到作用了 1.打开Navicat,选择工具--数据同步 2.选择好要同步的数据库和被同步的数据库 3.下一步 4....

    以体测为例,我在开发库中的tt_student表导入了一批学生,此时开发库中tt_student表的数据是最新的。

    但测试库里tt_student表也需要更新,由于学生数量过于庞大,再重新导入的话费时费力,那么数据同步起到作用了


    1.打开Navicat,选择工具--数据同步

    2.选择好要同步的数据库和被同步的数据库

     3.下一步

     

    4.取消全选后选择要同步的对应的表,点击比对

     

     

    5.从下面的界面可以看出从源表tp_student要向目标表tp_student表插入5519条数据

     

    6. 确认信息无误后点击部署就可以了,因为已经同步过,部署的过程不再演示

    展开全文
  • 线程同步作用

    千次阅读 2013-08-26 21:11:39
    线程同步 我们可以在计算机上运行各种计算机软件程序。每一个运行的程序可能包括多个独立运行的线程(Thread)。 线程(Thread)是一份独立运行的程序,有自己专用的运行栈。线程有可能和其他线程共享一些资源,...
    这是javaeye上非常经典的关于线程的帖子,写的非常通俗易懂的,适合任何读计算机的同学. 
    线程同步
    
    我们可以在计算机上运行各种计算机软件程序。每一个运行的程序可能包括多个独立运行的线程(Thread)。 
    线程(Thread)是一份独立运行的程序,有自己专用的运行栈。线程有可能和其他线程共享一些资源,比如,内存,文件,数据库等。 
    当多个线程同时读写同一份共享资源的时候,可能会引起冲突。这时候,我们需要引入线程“同步”机制,即各位线程之间要有个先来后到,不能一窝蜂挤上去抢作一团。 
    同步这个词是从英文synchronize(使同时发生)翻译过来的。我也不明白为什么要用这个很容易引起误解的词。既然大家都这么用,咱们也就只好这么将就。 
    线程同步的真实意思和字面意思恰好相反。线程同步的真实意思,其实是“排队”:几个线程之间要排队,一个一个对共享资源进行操作,而不是同时进行操作。
    
    因此,关于线程同步,需要牢牢记住的第一点是:线程同步就是线程排队。同步就是排队。线程同步的目的就是避免线程“同步”执行。这可真是个无聊的绕口令。 
    关于线程同步,需要牢牢记住的第二点是 “共享”这两个字。只有共享资源的读写访问才需要同步。如果不是共享资源,那么就根本没有同步的必要。 
    关于线程同步,需要牢牢记住的第三点是,只有“变量”才需要同步访问。如果共享的资源是固定不变的,那么就相当于“常量”,线程同时读取常量也不需要同步。至少一个线程修改共享资源,这样的情况下,线程之间就需要同步。 
    关于线程同步,需要牢牢记住的第四点是:多个线程访问共享资源的代码有可能是同一份代码,也有可能是不同的代码;无论是否执行同一份代码,只要这些线程的代码访问同一份可变的共享资源,这些线程之间就需要同步。
    
    为了加深理解,下面举几个例子。 
    有两个采购员,他们的工作内容是相同的,都是遵循如下的步骤: 
    (1)到市场上去,寻找并购买有潜力的样品。 
    (2)回到公司,写报告。 
    这两个人的工作内容虽然一样,他们都需要购买样品,他们可能买到同样种类的样品,但是他们绝对不会购买到同一件样品,他们之间没有任何共享资源。所以,他们可以各自进行自己的工作,互不干扰。 
    这两个采购员就相当于两个线程;两个采购员遵循相同的工作步骤,相当于这两个线程执行同一段代码。
    
    下面给这两个采购员增加一个工作步骤。采购员需要根据公司的“布告栏”上面公布的信息,安排自己的工作计划。 
    这两个采购员有可能同时走到布告栏的前面,同时观看布告栏上的信息。这一点问题都没有。因为布告栏是只读的,这两个采购员谁都不会去修改布告栏上写的信息。
    
    下面增加一个角色。一个办公室行政人员这个时候,也走到了布告栏前面,准备修改布告栏上的信息。 
    如果行政人员先到达布告栏,并且正在修改布告栏的内容。两个采购员这个时候,恰好也到了。这两个采购员就必须等待行政人员完成修改之后,才能观看修改后的信息。 
    如果行政人员到达的时候,两个采购员已经在观看布告栏了。那么行政人员需要等待两个采购员把当前信息记录下来之后,才能够写上新的信息。 
    上述这两种情况,行政人员和采购员对布告栏的访问就需要进行同步。因为其中一个线程(行政人员)修改了共享资源(布告栏)。而且我们可以看到,行政人员的工作流程和采购员的工作流程(执行代码)完全不同,但是由于他们访问了同一份可变共享资源(布告栏),所以他们之间需要同步。
    
    同步锁
    
    前面讲了为什么要线程同步,下面我们就来看如何才能线程同步。 
    线程同步的基本实现思路还是比较容易理解的。我们可以给共享资源加一把锁,这把锁只有一把钥匙。哪个线程获取了这把钥匙,才有权利访问该共享资源。 
    生活中,我们也可能会遇到这样的例子。一些超市的外面提供了一些自动储物箱。每个储物箱都有一把锁,一把钥匙。人们可以使用那些带有钥匙的储物箱,把东西放到储物箱里面,把储物箱锁上,然后把钥匙拿走。这样,该储物箱就被锁住了,其他人不能再访问这个储物箱。(当然,真实的储物箱钥匙是可以被人拿走复制的,所以不要把贵重物品放在超市的储物箱里面。于是很多超市都采用了电子密码锁。) 
    线程同步锁这个模型看起来很直观。但是,还有一个严峻的问题没有解决,这个同步锁应该加在哪里? 
    当然是加在共享资源上了。反应快的读者一定会抢先回答。 
    没错,如果可能,我们当然尽量把同步锁加在共享资源上。一些比较完善的共享资源,比如,文件系统,数据库系统等,自身都提供了比较完善的同步锁机制。我们不用另外给这些资源加锁,这些资源自己就有锁。 
    但是,大部分情况下,我们在代码中访问的共享资源都是比较简单的共享对象。这些对象里面没有地方让我们加锁。 
    读者可能会提出建议:为什么不在每一个对象内部都增加一个新的区域,专门用来加锁呢?这种设计理论上当然也是可行的。问题在于,线程同步的情况并不是很普遍。如果因为这小概率事件,在所有对象内部都开辟一块锁空间,将会带来极大的空间浪费。得不偿失。 
    于是,现代的编程语言的设计思路都是把同步锁加在代码段上。确切的说,是把同步锁加在“访问共享资源的代码段”上。这一点一定要记住,同步锁是加在代码段上的。 
    同步锁加在代码段上,就很好地解决了上述的空间浪费问题。但是却增加了模型的复杂度,也增加了我们的理解难度。 
    现在我们就来仔细分析“同步锁加在代码段上”的线程同步模型。 
    首先,我们已经解决了同步锁加在哪里的问题。我们已经确定,同步锁不是加在共享资源上,而是加在访问共享资源的代码段上。 
    其次,我们要解决的问题是,我们应该在代码段上加什么样的锁。这个问题是重点中的重点。这是我们尤其要注意的问题:访问同一份共享资源的不同代码段,应该加上同一个同步锁;如果加的是不同的同步锁,那么根本就起不到同步的作用,没有任何意义。 
    这就是说,同步锁本身也一定是多个线程之间的共享对象。
    
    Java语言的synchronized关键字
    
    为了加深理解,举几个代码段同步的例子。 
    不同语言的同步锁模型都是一样的。只是表达方式有些不同。这里我们以当前最流行的Java语言为例。Java语言里面用synchronized关键字给代码段加锁。整个语法形式表现为 
    synchronized(同步锁) { 
    // 访问共享资源,需要同步的代码段 
    }
    
    这里尤其要注意的就是,同步锁本身一定要是共享的对象。
    
    … f1() {
    
    Object lock1 = new Object(); // 产生一个同步锁
    
    synchronized(lock1){ 
    // 代码段 A 
    // 访问共享资源 resource1 
    // 需要同步 
    } 
    }
    
    上面这段代码没有任何意义。因为那个同步锁是在函数体内部产生的。每个线程调用这段代码的时候,都会产生一个新的同步锁。那么多个线程之间,使用的是不同的同步锁。根本达不到同步的目的。 
    同步代码一定要写成如下的形式,才有意义。
    
    public static final Object lock1 = new Object();
    
    … f1() {
    
    synchronized(lock1){ // lock1 是公用同步锁 
    // 代码段 A 
    // 访问共享资源 resource1 
    // 需要同步 
    }
    
    你不一定要把同步锁声明为static或者public,但是你一定要保证相关的同步代码之间,一定要使用同一个同步锁。 
    讲到这里,你一定会好奇,这个同步锁到底是个什么东西。为什么随便声明一个Object对象,就可以作为同步锁? 
    在Java里面,同步锁的概念就是这样的。任何一个Object Reference都可以作为同步锁。我们可以把Object Reference理解为对象在内存分配系统中的内存地址。因此,要保证同步代码段之间使用的是同一个同步锁,我们就要保证这些同步代码段的synchronized关键字使用的是同一个Object Reference,同一个内存地址。这也是为什么我在前面的代码中声明lock1的时候,使用了final关键字,这就是为了保证lock1的Object Reference在整个系统运行过程中都保持不变。 
    一些求知欲强的读者可能想要继续深入了解synchronzied(同步锁)的实际运行机制。Java虚拟机规范中(你可以在google用“JVM Spec”等关键字进行搜索),有对synchronized关键字的详细解释。synchronized会编译成 monitor enter, … monitor exit之类的指令对。Monitor就是实际上的同步锁。每一个Object Reference在概念上都对应一个monitor。 
    这些实现细节问题,并不是理解同步锁模型的关键。我们继续看几个例子,加深对同步锁模型的理解。
    
    public static final Object lock1 = new Object();
    
    … f1() {
    
    synchronized(lock1){ // lock1 是公用同步锁 
    // 代码段 A 
    // 访问共享资源 resource1 
    // 需要同步 
    } 
    }
    
    … f2() {
    
    synchronized(lock1){ // lock1 是公用同步锁 
    // 代码段 B 
    // 访问共享资源 resource1 
    // 需要同步 
    } 
    }
    
    上述的代码中,代码段A和代码段B就是同步的。因为它们使用的是同一个同步锁lock1。 
    如果有10个线程同时执行代码段A,同时还有20个线程同时执行代码段B,那么这30个线程之间都是要进行同步的。 
    这30个线程都要竞争一个同步锁lock1。同一时刻,只有一个线程能够获得lock1的所有权,只有一个线程可以执行代码段A或者代码段B。其他竞争失败的线程只能暂停运行,进入到该同步锁的就绪(Ready)队列。 
    每一个同步锁下面都挂了几个线程队列,包括就绪(Ready)队列,待召(Waiting)队列等。比如,lock1对应的就绪队列就可以叫做lock1 - ready queue。每个队列里面都可能有多个暂停运行的线程。 
    注意,竞争同步锁失败的线程进入的是该同步锁的就绪(Ready)队列,而不是后面要讲述的待召队列(Waiting Queue,也可以翻译为等待队列)。就绪队列里面的线程总是时刻准备着竞争同步锁,时刻准备着运行。而待召队列里面的线程则只能一直等待,直到等到某个信号的通知之后,才能够转移到就绪队列中,准备运行。 
    成功获取同步锁的线程,执行完同步代码段之后,会释放同步锁。该同步锁的就绪队列中的其他线程就继续下一轮同步锁的竞争。成功者就可以继续运行,失败者还是要乖乖地待在就绪队列中。 
    因此,线程同步是非常耗费资源的一种操作。我们要尽量控制线程同步的代码段范围。同步的代码段范围越小越好。我们用一个名词“同步粒度”来表示同步代码段的范围。 
    同步粒度 
    在Java语言里面,我们可以直接把synchronized关键字直接加在函数的定义上。 
    比如。 
    … synchronized … f1() { 
    // f1 代码段 
    }
    
    这段代码就等价于 
    … f1() { 
    synchronized(this){ // 同步锁就是对象本身 
    // f1 代码段 
    } 
    }
    
    同样的原则适用于静态(static)函数 
    比如。 
    … static synchronized … f1() { 
    // f1 代码段 
    }
    
    这段代码就等价于 
    …static … f1() { 
    synchronized(Class.forName(…)){ // 同步锁是类定义本身 
    // f1 代码段 
    } 
    }
    
    但是,我们要尽量避免这种直接把synchronized加在函数定义上的偷懒做法。因为我们要控制同步粒度。同步的代码段越小越好。synchronized控制的范围越小越好。 
    我们不仅要在缩小同步代码段的长度上下功夫,我们同时还要注意细分同步锁。 
    比如,下面的代码
    
    public static final Object lock1 = new Object();
    
    … f1() {
    
    synchronized(lock1){ // lock1 是公用同步锁 
    // 代码段 A 
    // 访问共享资源 resource1 
    // 需要同步 
    } 
    }
    
    … f2() {
    
    synchronized(lock1){ // lock1 是公用同步锁 
    // 代码段 B 
    // 访问共享资源 resource1 
    // 需要同步 
    } 
    }
    
    … f3() {
    
    synchronized(lock1){ // lock1 是公用同步锁 
    // 代码段 C 
    // 访问共享资源 resource2 
    // 需要同步 
    } 
    }
    
    … f4() {
    
    synchronized(lock1){ // lock1 是公用同步锁 
    // 代码段 D 
    // 访问共享资源 resource2 
    // 需要同步 
    } 
    }
    
    上述的4段同步代码,使用同一个同步锁lock1。所有调用4段代码中任何一段代码的线程,都需要竞争同一个同步锁lock1。 
    我们仔细分析一下,发现这是没有必要的。 
    因为f1()的代码段A和f2()的代码段B访问的共享资源是resource1,f3()的代码段C和f4()的代码段D访问的共享资源是resource2,它们没有必要都竞争同一个同步锁lock1。我们可以增加一个同步锁lock2。f3()和f4()的代码可以修改为: 
    public static final Object lock2 = new Object();
    
    … f3() {
    
    synchronized(lock2){ // lock2 是公用同步锁 
    // 代码段 C 
    // 访问共享资源 resource2 
    // 需要同步 
    } 
    }
    
    … f4() {
    
    synchronized(lock2){ // lock2 是公用同步锁 
    // 代码段 D 
    // 访问共享资源 resource2 
    // 需要同步 
    } 
    }
    
    这样,f1()和f2()就会竞争lock1,而f3()和f4()就会竞争lock2。这样,分开来分别竞争两个锁,就可以大大较少同步锁竞争的概率,从而减少系统的开销。
    
    信号量
    
    同步锁模型只是最简单的同步模型。同一时刻,只有一个线程能够运行同步代码。 
    有的时候,我们希望处理更加复杂的同步模型,比如生产者/消费者模型、读写同步模型等。这种情况下,同步锁模型就不够用了。我们需要一个新的模型。这就是我们要讲述的信号量模型。 
    信号量模型的工作方式如下:线程在运行的过程中,可以主动停下来,等待某个信号量的通知;这时候,该线程就进入到该信号量的待召(Waiting)队列当中;等到通知之后,再继续运行。 
    很多语言里面,同步锁都由专门的对象表示,对象名通常叫Monitor。 
    同样,在很多语言中,信号量通常也有专门的对象名来表示,比如,Mutex,Semphore。 
    信号量模型要比同步锁模型复杂许多。一些系统中,信号量甚至可以跨进程进行同步。另外一些信号量甚至还有计数功能,能够控制同时运行的线程数。 
    我们没有必要考虑那么复杂的模型。所有那些复杂的模型,都是最基本的模型衍生出来的。只要掌握了最基本的信号量模型——“等待/通知”模型,复杂模型也就迎刃而解了。 
    我们还是以Java语言为例。Java语言里面的同步锁和信号量概念都非常模糊,没有专门的对象名词来表示同步锁和信号量,只有两个同步锁相关的关键字——volatile和synchronized。 
    这种模糊虽然导致概念不清,但同时也避免了Monitor、Mutex、Semphore等名词带来的种种误解。我们不必执着于名词之争,可以专注于理解实际的运行原理。 
    在Java语言里面,任何一个Object Reference都可以作为同步锁。同样的道理,任何一个Object Reference也可以作为信号量。 
    Object对象的wait()方法就是等待通知,Object对象的notify()方法就是发出通知。 
    具体调用方法为 
    (1)等待某个信号量的通知 
    public static final Object signal = new Object();
    
    … f1() { 
    synchronized(singal) { // 首先我们要获取这个信号量。这个信号量同时也是一个同步锁
    
    // 只有成功获取了signal这个信号量兼同步锁之后,我们才可能进入这段代码 
    signal.wait(); // 这里要放弃信号量。本线程要进入signal信号量的待召(Waiting)队列
    
    // 可怜。辛辛苦苦争取到手的信号量,就这么被放弃了
    
    // 等到通知之后,从待召(Waiting)队列转到就绪(Ready)队列里面 
    // 转到了就绪队列中,离CPU核心近了一步,就有机会继续执行下面的代码了。 
    // 仍然需要把signal同步锁竞争到手,才能够真正继续执行下面的代码。命苦啊。 
    … 
    } 
    }
    
    需要注意的是,上述代码中的signal.wait()的意思。signal.wait()很容易导致误解。signal.wait()的意思并不是说,signal开始wait,而是说,运行这段代码的当前线程开始wait这个signal对象,即进入signal对象的待召(Waiting)队列。
    
    (2)发出某个信号量的通知 
    … f2() { 
    synchronized(singal) { // 首先,我们同样要获取这个信号量。同时也是一个同步锁。
    
    // 只有成功获取了signal这个信号量兼同步锁之后,我们才可能进入这段代码 
    signal.notify(); // 这里,我们通知signal的待召队列中的某个线程。
    
    // 如果某个线程等到了这个通知,那个线程就会转到就绪队列中 
    // 但是本线程仍然继续拥有signal这个同步锁,本线程仍然继续执行 
    // 嘿嘿,虽然本线程好心通知其他线程, 
    // 但是,本线程可没有那么高风亮节,放弃到手的同步锁 
    // 本线程继续执行下面的代码 
    … 
    } 
    }
    
    需要注意的是,signal.notify()的意思。signal.notify()并不是通知signal这个对象本身。而是通知正在等待signal信号量的其他线程。
    
    以上就是Object的wait()和notify()的基本用法。 
    实际上,wait()还可以定义等待时间,当线程在某信号量的待召队列中,等到足够长的时间,就会等无可等,无需再等,自己就从待召队列转移到就绪队列中了。 
    另外,还有一个notifyAll()方法,表示通知待召队列里面的所有线程。 
    这些细节问题,并不对大局产生影响。
    
    绿色线程
    
    绿色线程(Green Thread)是一个相对于操作系统线程(Native Thread)的概念。 
    操作系统线程(Native Thread)的意思就是,程序里面的线程会真正映射到操作系统的线程,线程的运行和调度都是由操作系统控制的 
    绿色线程(Green Thread)的意思是,程序里面的线程不会真正映射到操作系统的线程,而是由语言运行平台自身来调度。 
    当前版本的Python语言的线程就可以映射到操作系统线程。当前版本的Ruby语言的线程就属于绿色线程,无法映射到操作系统的线程,因此Ruby语言的线程的运行速度比较慢。 
    难道说,绿色线程要比操作系统线程要慢吗?当然不是这样。事实上,情况可能正好相反。Ruby是一个特殊的例子。线程调度器并不是很成熟。 
    目前,线程的流行实现模型就是绿色线程。比如,stackless Python,就引入了更加轻量的绿色线程概念。在线程并发编程方面,无论是运行速度还是并发负载上,都优于Python。 
    另一个更著名的例子就是ErLang(爱立信公司开发的一种开源语言)。 
    ErLang的绿色线程概念非常彻底。ErLang的线程不叫Thread,而是叫做Process。这很容易和进程混淆起来。这里要注意区分一下。 
    ErLang Process之间根本就不需要同步。因为ErLang语言的所有变量都是final的,不允许变量的值发生任何变化。因此根本就不需要同步。 
    final变量的另一个好处就是,对象之间不可能出现交叉引用,不可能构成一种环状的关联,对象之间的关联都是单向的,树状的。因此,内存垃圾回收的算法效率也非常高。这就让ErLang能够达到Soft Real Time(软实时)的效果。这对于一门支持内存垃圾回收的语言来说,可不是一件容易的事情。
    展开全文
  • 1、为什么需要主从同步,设置主从同步有什么样的作用? 2、主从同步的原理是怎样的?在进行主从同步的同时会引入哪些问题? 3、为了保证主从同步的数据一致性,都有哪些方案? 为什么需要主从同步 首先不是...

    Redis是一种高性能的内存数据库;而MySQL是基于磁盘文件的关系型数据库,相比于Redis来说,读取速度会慢一些,但是功能强大,可以用于存储持久化的数据。在实际工作中,我们常常将Redis作为缓存与MySQL配合来使用,当有数据访问请求的时候,首先会从缓存中进行查找,如果存在就直接取出,如果不存在再访问数据库,这样就提升了读取的效率,也减少了堆后端数据库的访问压力。可以说使用Redis这种缓存架构是高并发架构中非常重要的一环。

    在这里插入图片描述

    当然我们也可以对MySQL做主从架构并且进行读写分离,让主服务器(Master)处理写请求,从服务器(Slave)处理读请求,这样同样可以提升数据库的并发处理能力。不过主从架构的作用不止如此,我们今天就从下面几个方面了解一下它:

    1、为什么需要主从同步,设置主从同步有什么样的作用?
    2、主从同步的原理是怎样的?在进行主从同步的同时会引入哪些问题?
    3、为了保证主从同步的数据一致性,都有哪些方案?

    为什么需要主从同步

    首先不是所有的应用都需要对数据库进行主从架构的设置,毕竟设置架构本身是有成本的,如果我们的目的在于提升数据库高并发访问的效率,那么首先需要考虑的应该是如何优化你的SQL和索引,这种方式简单有效,其次才是采用缓存的策略,比如使用Redis,通过Redis高性能的优势把热点数据保存在内存数据库中,提升读取的效率,最后才是对数据库采用主从架构,进行读写分离。

    按照上面的方式进行优化,使用和维护的成本是由小到大的。

    主从同步设计不仅可以提升数据库的吞吐量,还有以下三个方面的作用。

    首先是可以读写分离,我们可以通过主从复制的方式来同步数据,然后通过读写分离提升数据库的并发处理能力。

    简单来说就是同一份数据被放在了多个数据库中,其中一个数据库是Master主库,其余的多个数据库是Slave从库。当主库进行更新的时候,会自动将数据复制到从库中,而我们在客户端读取数据的时候,会从从库进行读取,也就是采用读写分离的方式。互联网的应用往往是“读多写少”的需求,采用读写分离的方式,可以实现更高的并发访问。原本所有的读写压力都由一台服务器承担,现在有多个“兄弟”帮忙处理读请求,这样就减少了对后端大哥(Maste)的压力。同时,我们还能对从服务器进行负载均衡,让不同的读请求按照策略均匀的分配到不同的从服务器中,让读取更加顺畅。读取顺畅的另一个原因,就是减少了锁表的影响,比如我们让主库负责写,当主库出现写锁的时候,不会影响到从库进行SELECT操作。

    第二个作用就是数据备份。我们通过主从复制将主库上的数据复制到了从库上,相当于是一种热备份机制,也就是在主库正常运行下进行备份,不会影响到服务。

    第三个作用是具有高可用性。我刚才讲的数据备份实际上是一种冗余的机制,通过这种冗余的方式可以换取数据库的高可用性,也就是当服务器出现故障或者宕机的情况下,可以切换到从服务器上,让从服务器充当主服务器,保证服务的正常运行。

    关于高可用性的程度,我们可以用一个指标衡量,既正常可用时间 / 全年时间。比如要达到全年99.999%的时间都可用,就意味着系统在一年中的不可用时间不得超过5.256分钟,其他时间都需要保持可用的状态。需要注意的是,这5.256分钟包括了系统崩溃的时间,也包括了日常维护操作导致的停机时间。

    事实上,更高的高可用性,意味着需要付出更高的成本代价,在现实中我们需要结合业务需求和成本来进行选择。

    主从同步的原理是怎样的

    提到主从同步的原理,我们就需要了解在数据库中的一个重要日志文件,那就是Binlog二进制文件,它记录了对数据库进行更新的事件,事实上主从同步的原理就是基于Binlog进行数据同步的。在主从复制过程中,会基于三个线程来操作,一个主库线程,两个从库线程。

    二进制日志转储线程是一个主库线程。当从库线程连接的时候,主库可以将二进制日志发送到从库,当主库读取事件的时候,会在Binglog上加锁,读取完成之后,再将锁释放掉。

    从库IO线程会连接到主库,向主库发送请求更新Binlog,这时从库的IO线程就可以读取到主库的二进制日志转储线程发送的Binlog更新部分,并且拷贝到本地形成中继日志(Relay log)。

    从库SQL线程会读取从库中的中继日志,并且执行日志中的事件,从而将从库中的数据与主库保持同步。

    在这里插入图片描述

    你能看到主从同步的内容就是二进制日志(Binlog),它虽然叫二进制日志,实际上存储的是一个又一个的事件(Event),这些事件分别对应着数据库的更新操作,比如INSERT、UPDATE、DELETE等。另外我们还需要注意的是,不是所有版本的MySQL都默认开启了服务器的二进制日志,在进行主从同步的时候,我们需要先检查服务器是否已经开启了二进制日志。

    进行主从同步的内容是二进制日志,它是一个文件,在进行网络传输的过程中就一定会存在延迟,比如500ms,这样就可能造成用户在从库上读取的数据不是最新的数据,也就是主从同步中的数据不一致问题。比如我们对一条记录进行更新,这个操作是在主库上完成的,而在很短的时间内,比如100ms,又对同一个记录进行读取,这时候从库还没有完成数据的读取,那么,我们通过从库读取到的数据就是一条旧的数据。

    这种情况下该怎么办呢?

    如何解决主从同步的数据一致性问题

    可以想象下,如果我们想要操作的数据都存储在同一个数据库中,那么对数据进行更新的时候,可以对记录进行加写锁,这样在读取的时候就不会发生数据不一致的情况了。但这时从库的作用就是备份数据,没有做到读写分离,分担主库的压力。

    在这里插入图片描述

    因此我们还需要想办法,在进行读写分离的时候,解决主从同步中数据不一致的问题,也就是解决主从之间数据复制方式的问题,如果按照数据一致性从弱到强来进行划分,有以下三种复制方式。

    方式1:异步复制

    异步模式就是客户端提交COMMIT之后不需要等从库返回任何结果,而是直接将结果返回给客户端,这样做的好处就是不会影响主库的执行效率,但是可能会存在主库宕机,而Binlog还没有同步到从库的情况,也就是主库和从库的数据不一致问题,这时候从从库中选一个作为新的主库,那么,新的主库则可能会缺少原来主服务器中已经提交的事务。所以,这种复制模式下的数据一致性是最弱的。

    在这里插入图片描述

    方式2:半同步复制

    MySQL5.5版本之后开始支持半同步复制的方式。原理是在客户端提交COMMIT之后不直接将结果返回给客户端,而是等待至少有一个从库收到了Binlog,并且写入到中继日志中,再返回给客户端。这样做的好处就是提高了数据的一致性,当然相比于异步复制来说,至少多增加了一个网络连接的延迟,降低了主库写的效率。

    在MySQL5.7版本中还增加了一个rpl_semi_sync_master_wait_for_slave_count参数,我们可以对应搭的从库数量进行设置,默认为1,也就是说只要有一个从库进行了响应,就可以返回给客户端。如果将这个参数调大,可以提升数据一致性的强度,但也会增加主库等待从库响应的时间。

    在这里插入图片描述

    方式3:组复制

    组复制技术,简称MGR。是MySQL在5.7.17版本中推出的一种新的数据复制技术,这种复制技术是基于paxos协议的状态机复制。

    我刚才介绍的异步复制和半同步复制都无法最终保证数据的一致性问题,半同步复制是通过判断从库响应的个数来决定是否返回给客户端,虽然数据一致性相比于异步复制有提升,但仍然无法满足对数据一致性要求高的场景,比如金融领域。MGR 很好地弥补了这两种复制模式的不足。

    下面我们来看下 MGR 是如何工作的(如下图所示)。

    首先我们将多个节点共同组成一个复制组,在执行读写(RW)事务的时候,需要通过一致性协议层(Consensus)的同意,也就是读写事务想要进行提交,必须要经过组里“大多数人”(对应Node节点)的同意,大多数指的是同意的节点数量要大于N/2+1,这样才可以进行提交,而不是一方说了算。而针对只读(RO)事务则不需要经过组内同意,直接COMMIT即可。

    在一个复制组内有多个节点组成,它们各自维护了自己的数据副本,并且在一致性协议层实现了源自消息和全局有序消息,从而保证组内数据的一致性。(具体原理点击这里可以参考)。

    在这里插入图片描述

    MGR将MySQL带入了数据强一致性的时代,是一个划时代的创新,其中一个重要原因是MGR是基于paxos协议的。PAxos算法是由2013 年的图灵奖获得者 Leslie Lamport 于 1990 年提出的,有关这个算法的决策机制你可以去网上搜下。

    事实上,Paxos算法提出来之后就作为分布式一致性算法被广泛使用,比如Apache的Zookeeper也是基于paxos算法实现的。

    总结

    我今天讲解了数据库的主从同步,如果你的目标仅仅是数据库的高并发,那么可以先从 SQL 优化,索引以及 Redis 缓存数据库这些方面来考虑优化,然后再考虑是否采用主从架构的方式。

    在主从架构的配置中,如果想要采取读写分离的策略,我们可以自己编写程序,也可以通过第三方的中间件来实现。

    自己编写程序的好处就在于比较自主,我们可以自己判断哪些查询在从库上来执行,针对实时性要求高的需求,我们还可以考虑哪些查询可以在主库上执行。同时,程序直接连接数据库,减少了中间件层,相当于减少了性能损耗。

    采用中间件的方法有很明显的优势,功能强大,使用简单。但因为在客户端和数据库之间增加了中间件层会有一些性能损耗,同时商业中间件也是有使用成本的。我们也可以考虑采取一些优秀的开源工具,比如 MaxScale。它是 MariaDB 开发的 MySySQL 数据中间件。比如在下图中,使用 MaxScale作为数据库的代理,通过路由转发完成了读写分离。同时我们也可以使用 MHA 工具作为强一致的主从切换工具,从而完成 MySQL的高可用架构。

    在这里插入图片描述

    在这里插入图片描述

    展开全文
  • web页面数据没有更新,刚开始老夫以为同步断了,上了服务器查看数据库同步状态(show slave status\G),发现是双yes,以为是数据太多堵塞没同步过来呢,待会应该就会好了,第二天看了一眼还是没有同步,查看同步...

    web页面数据没有更新,刚开始老夫以为同步断了,上了服务器查看数据库同步状态(show slave status\G),发现是双yes,以为是数据太多堵塞没同步过来呢,待会应该就会好了,第二天看了一眼还是没有同步,查看同步状态还是双yes,同步的位置(pos)和主库是一样的,主库有数据从库没有,然后找错误日志,没有异常输出,主库从库都是这样,没有异常,查看binlog也是有的,后来在从库手动插入1条id是99999数据,提示id99999主键重复,查看了一下,id主键是99999没有数据,应该可以正常插入的,后来把主库的表导了一份导入到从库中,然后追加进去了,没有报错,然后老夫在主库添加一条数据,从库没有更新,老夫又给测试数据删了,有一些表是同步的,插入数据也是直接同步了,有一些就是不行,后来想起来,前天改表引擎了,而这几个表有触发器,当A表插入数据的时候触发器会插入同样的数据到B表中,前天改表引擎从MYISAM改成innodb,只改了B表的,A表的后来忘了改,猜测是不是这个原因,给A表引擎改成innodb之后,再添加测试数据,发现已经同步了,然后把那些带触发器的A表的引擎都改成innodb,问题解决。

    展开全文
  • 比如从oracle数据库中同步一张的数据到Mysql中,通常的做法就是 分页查询源端的,然后通过 jdbc的batch 方式插入到目标,这个地方需要注意的是,分页查询时,一定要按照主键id来排序分页,避免重复插入。...
  • 同步,帧同步是什么意思

    千次阅读 2019-04-08 12:57:45
    同步,帧同步是什么意思 在数字通信时,一般总是以一定数目的码元组成一个个的“字”或“句”,即组成一个个的“群”进行传输的。因此,群同步信号的频率很容易由位同步信号经分频而得出。但是,每个群的开头和末尾...
  • Java面试题大全(2020版)

    万次阅读 多人点赞 2019-11-26 11:59:06
    HashMap概述: HashMap是基于哈希的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。 HashMap的数据结构: 在java编程...
  • oracle两个数据同步备份

    千次阅读 2018-12-06 14:29:16
    这段时间做sqoop2数据导出,需要先将数据导入到中间,然后将中间的数据同步到目的,中间和目的表字段完全一样,只是的名称不一致。 方式一:触发器 触发器:是一个与相关联的、存储的PL/SQL程序。每当...
  • 需求:同步不同服务器上的数据库的数据。 说明:现有服务器A,服务器B。需要在插入(修改|删除)A上的用户数据sourceTable的同时,操作B上用户remoteTable与A中一致;如:在项目A中注册用户后,需要在B中也可以...
  • 当您将两个表同步到es时,一个不起作用将阻止另一个。 因此,我们将两个的数据发送给具有不同主题的kafka,两个将独立工作。 快速开始 安装jdk(> = 1.8),安装kafka(> = 0.9.0.1) 从下载eays-sync, ...
  • UE4网络同步(二)——深入同步细节

    万次阅读 多人点赞 2017-10-29 11:54:18
    我这里主要是从同步的流程分析,以同步的机制为讲解核心,给大家描述里面是怎么同步的,会大量涉及UE同步模块的底层代码,稍微涉及一点计算机网络底层(Socket相关)相关的知识。 PS:如果只是想知道怎么使用同步,...
  • 解决ClickHouse的去重ReplacingMergeTree引擎数据无法自动同步问题 问题描述: 建立了2个分片,每个分片下面有2个节点,互相做为备份,但是实际中,副本数据并没有在后台同步,一般zk会进行异步同步 原因分析: ...
  • UE4网络同步详解(一)——理解同步规则

    万次阅读 多人点赞 2017-10-15 21:41:40
    这篇文章主要以问题的形式,针对UE同步的各个方面的内容,做一个详细而充分的讨论。对于新手理解UE的同步机制非常有帮助,对于有一定的基础而没有深入的UE程序也或许有一些启发。如果想深入了解同步的实现原理,可以...
  • MySQL 面试题

    万次阅读 多人点赞 2019-09-02 16:03:33
    中有大字段 X(例如:text 类型),且字段 X 不会经常更新,以读为为主,请问您是选择拆成子,还是继续放一起?写出您这样选择的理由 拆带来的问题:连接消耗 + 存储拆分空间。 如果能容忍拆分带来的空间...
  • 绘制完原理图后,要将器件和网络导入PCB需要进行网导入的工作,在新建PCB并保存后,在原理图界面使用快捷键D+U(Design + Update)可以实现从原理图到PCB的同步的功能。同样,在PCB界面使用快捷键D+I(Design+...
  • 2020最新Java常见面试题及答案

    万次阅读 多人点赞 2019-10-26 15:53:35
    160.zookeeper 怎么保证主从节点的状态同步? 161.集群中为什么要有主节点? 162.集群中有 3 台服务器,其中一个节点宕机,这个时候 zookeeper 还可以使用吗? 163.说一下 zookeeper 的通知机制? 十七、MySql 164....
  • 作用:增加tab1记录后自动将记录增加到tab2中 delimiter ||  DROP TRIGGER IF EXISTS t_afterinsert_on_tab1 || CREATE TRIGGER t_afterinsert_on_tab1  AFTER INSERT ON tab1 FOR EACH ...
  • 大数据开发平台-数据同步服务

    万次阅读 2017-09-21 13:38:35
    同步一切
  • Oracle入门到实战

    万次阅读 多人点赞 2019-11-09 11:12:07
    Oracle学习:Oracle基础语句、Oracle查询关键字、Oracle常用函数、Oracle常用结构
  • java面试题2019_java面试题及答案_java面试题库

    千次阅读 多人点赞 2019-05-16 09:31:30
    1、一个.java源文件中是否...4、switch语句能否作用在byte上,能否作用在long上,能否作用在String上? 5、short s1 = 1; s1 = s1 + 1;有什么错?short s1 = 1; s1 += 1;有什么错? 6、char型变量中能不能存贮一个中...
  • Replication作为一种准实时同步方式,得到广泛应用。这个时候的Replicaton的实现涉及到两个线程,一个在Master,一个在Slave。Slave的I/O和SQL功能是作为一个线程,从Master获取到event后直接apply,没有r...
  • 详解kettle数据同步-图文

    千次阅读 2018-04-18 17:44:25
    下载完成解压 需要在本地启动一个spoon.bat 刚刚解压的kettle压缩包 在window linux也是可以使用 然后编写ktr文件 目前需求是将某个库的数据导入到某张表当中 创建输入步骤 然后创建插入更...
  • 现在需要mysql几张实时同步到一个地方,考虑到增量、性能问题,做出以下重要文档。 某几张实时同步 实时需求开发 一、技术组件调研 1.sqoop方式 无法实时 2.flume方式。 可以参考文章: ...
  • 什么是Handler的同步屏障 Handler中的Message可以分为两类:同步消息、异步消息。消息类型可以通过以下函数得知 //Message.java public boolean isAsynchronous() { return (flags & FLAG_ASYNCHRONOUS) != 0; ...
  • 【Kettle】—— Kettle增量同步变动数据

    万次阅读 多人点赞 2018-11-07 00:15:56
    最近在用kettle同步数据的时候,有增量同步的需求。 之前也遇到过这个需求,查阅了很多文章,也试了很多方法,都没有实现我所需的简洁的方式。 这回在我一次次尝试无果的情况下,突然间的灵光一闪,让我豁然开朗,...
  • Java集合面试题

    万次阅读 多人点赞 2019-06-25 14:46:19
    当与具体实现打交道的时候,克隆或序列化的语义和含义才发挥作用。所以,具体实现应该决定如何对它进行克隆或序列化,或它是否可以被克隆或序列化。在所有的实现中授权克隆和序列化,最终导致更少的灵活性和更多的...
  • 利用Kettle进行数据同步(上)

    万次阅读 2018-06-04 09:02:33
    写这篇文章,是源于公司内部的一个常见需求:将生产环境的数据同步到测试环境,以便更方便的进行测试和bug定位。 起初是用的Navicat Premium这款DB管理软件,功能非常强大了,足以满足开发人员的日常工作需求,也...
  • otter自定义数据同步踩坑实录

    千次阅读 2019-09-09 17:24:14
    otter自定义数据同步 otter支持数据处理自定义过程。 Extract模块: EventProcessor : 自定义数据处理,可以改变一条变更数据的任意内容 FileResolver : 解决数据和文件的关联关系 目前两者都只支持java语言...
  • MYSQL数据库间同步数据

    万次阅读 2018-05-24 19:49:01
    假设数据库A为主机,数据库B为从机(A向B提供同步服务,即B中的数据来自A)A机器:IP=10.10.151.166B机器:IP=10.10.151.156下面看单向同步的配置步骤:1 在机器A中建立一个新的数据库,sql语句:[sql] view plain...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 284,764
精华内容 113,905
关键字:

同步表作用