精华内容
下载资源
问答
  • 为什么还需要使用读写分离的Map?首先我们先介绍一下常用的Map线程不安全HashMap : 非线程安全,即任一时刻可以由多个线程同时写HashMap,可能会导致数据不一致。LinkedListHashMap: 非线程安全,保证 加入的顺序是...
    53203436594098543a3b4b9f293ef75c.png

    为什么还需要使用读写分离的Map?

    首先我们先介绍一下常用的Map

    1. 线程不安全
      • HashMap : 非线程安全,即任一时刻可以由多个线程同时写HashMap,可能会导致数据不一致。
      • LinkedListHashMap: 非线程安全,保证 加入的顺序是怎么,循环出来就是什么顺序。可以理解为维护了元素次序的HashMap。
      • TreeMap:有序的集合,可以实现自定义排序。

    2.线程安全

      • HashTable : 线程安全,但是读和写都需要加锁,性能比较低。
      • ConcurrentHashMap: 采用分段锁实现,但是同一段的写和读也是互斥的,所以性能稍微低

    那么如何实现一个缓存呢,可以进行并发的读和写的,从上面介绍类看,

    无论是HashTable 还是 ConcurrentHashMap 都会遇到读加锁的情况,所以不太适合这种场景。

    那么我们下面实现可以进行读写分离的Map,即写加锁,读不加锁。

    CopyOnWriteMap 的实现

    1、实现步骤如下

    1. 定义一个由初始容量的map.并使用volatile 修饰,这个为了保证在多线程环境下可见性。
    2. 定义一个 可重入锁 ReentrantLock
    3. 定义 put 方法,putAll方法,get方法

    2、代码实现

    0b27c6a36795640de438c2a4f9b9b9b3.png

    3、说明

    • put 方法
      • 首先加锁
      • new 一个新的Map,然后把旧的map放进去
      • 在新的Map中添加元素
      • 将旧map 的引用指向 新的 map
      • 释放锁
    • get 方法
      • get 方法不需要获取锁,直接获取即可。

    使用场景

    假如有下面一个场景,一个比较小的电商网站(商品信息比较少),所以我们可以直接缓存在内存中,

    后期添加、删除、更新都会更新内存中的缓存。

    实现代码如下:

    a1be8d7a6580109f9220fab63b95b543.png

    使用CopyOnWriteMap需要的注意事项:

    1、尽量批量添加,否则每次添加都会复制一个map容器,可能会造成频繁的GC(垃圾回收)。

    2、尽量初始化时指定容量

    CopyOnWriteMap 优缺点

    1. 优点
      1. 实现读写分离,读不加锁,写加锁,性能比较高,适合在高并发场景下使用。
      2. 对比HashTable 和 ConcurrentHashMap ,CopyOnWriteMap 优势在于读不加锁。并发高。
    2. 缺点
      1. 内存占用高的问题。
      2. 对写入的数据不能及时读出来

    下面说明为什么内存占用高:

    public V put(K key, V value) {try {lock.lock();Map newMap = new HashMap<>(map);V v = newMap.put(key, value);map = newMap;return v;} catch (Exception e) {}finally {lock.unlock();}return null;}

    从上面看,put操作首先 创建一个新的map,然后把添加的元素添加到新map中,

    最后把旧的 map引用指向新的map内存地址。

    示意图如下:

    1f9208a4b5a02f81bc19e83318963ddd.png

    执行 map = newMap; 代码后:

    20643603dd5eb9ac293450ed863bcc1e.png

    上面旧的map引用虽然指向了新的Map,但是旧的Map如果回收不及时,会造成内存溢出。

    为什么要使用COW ?

    9e26e01059751c15a67b9a32347a0b72.png

    java util 下的集合类都不能应付并发的修改和添加,比如在迭代集合的时候对此集合进行删除,

    则会出现 ConcurrentModificationException异常,或者 多个线程并发的添加,

    会出现 上一个添加的值被下一个值覆盖。

    为了应付并发的修改,有以下两种办法

    1、写时复制

    2、线程安全的容器

    比如: ArrayList --> CopyOnWriteList

    HashSet --> CopyOnWriteSet

    HashMap --> ConcurrentHashMap

    展开全文
  • 01.为什么还需要使用读写分离的Map?首先我们先介绍一下常用的Map线程不安全HashMap : 非线程安全,即任一时刻可以由多个线程同时写HashMap,可能会导致数据不一致。LinkedListHashMap: 非线程安全,保证 加入的顺序...

    01.为什么还需要使用读写分离的Map?

    首先我们先介绍一下常用的Map

    1. 线程不安全
    • HashMap : 非线程安全,即任一时刻可以由多个线程同时写HashMap,可能会导致数据不一致。
    • LinkedListHashMap: 非线程安全,保证 加入的顺序是怎么,循环出来就是什么顺序。可以理解为维护了元素次序的HashMap。
    • TreeMap:有序的集合,可以实现自定义排序。

    2.线程安全

      • HashTable : 线程安全,但是读和写都需要加锁,性能比较低。
      • ConcurrentHashMap: 采用分段锁实现,但是同一段的写和读也是互斥的,所以性能稍微低

    那么如何实现一个缓存呢,可以进行并发的读和写的,从上面介绍类看,

    无论是HashTable 还是 ConcurrentHashMap 都会遇到读加锁的情况,所以不太适合这种场景。

    那么我们下面实现可以进行读写分离的Map,即写加锁,读不加锁。

    02. CopyOnWriteMap 的实现

    1、实现步骤如下

    1. 定义一个由初始容量的map.并使用volatile 修饰,这个为了保证在多线程环境下可见性。
    2. 定义一个 可重入锁 ReentrantLock
    3. 定义 put 方法,putAll方法,get方法

    2、代码实现

    b9db4b37947b5e15cc51549f436e8169.png

    3、说明

    • put 方法
      • 首先加锁
      • new 一个新的Map,然后把旧的map放进去
      • 在新的Map中添加元素
      • 将旧map 的引用指向 新的 map
      • 释放锁
    • get 方法
      • get 方法不需要获取锁,直接获取即可。

    03. 使用场景

    假如有下面一个场景,一个比较小的电商网站(商品信息比较少),所以我们可以直接缓存在内存中,

    后期添加、删除、更新都会更新内存中的缓存。

    实现代码如下:

    968836a531ca57b2d11bbc0d426ac88d.png

    使用CopOnWriteMap需要的注意事项:

    1、尽量批量添加,否则每次添加都会复制一个map容器,可能会造成频繁的GC(垃圾回收)。

    2、尽量初始化时指定容量

    CopyOnWriteMap 优缺点

    1. 优点
      1. 实现读写分离,读不加锁,写加锁,性能比较高,适合在高并发场景下使用。
      2. 对比HashTable 和 ConcurrentHashMap ,CopyOnWriteMap 优势在于读不加锁。并发高。
    2. 缺点
      1. 内存占用高的问题。
      2. 对写入的数据不能及时读出来

    下面说明为什么内存占用高:

    public V put(K key, V value) {
    		try {
    			lock.lock();
    			Map<K,V> newMap = new HashMap<>(map);
    			V v = newMap.put(key, value);
    			map = newMap;
    			return v;
    		} catch (Exception e) {
    		}finally {
    			lock.unlock();
    		}
    		return null;
    	}

    从上面看,put操作首先 创建一个新的map,然后把添加的元素添加到新map中,

    最后把旧的 map引用指向新的map内存地址。

    示意图如下:

    84825a77c8e81f7e2ad610a365db8c99.png

    执行 map = newMap; 代码后:

    a31482d21420d82af4bf8dd202de4a01.png

    上面旧的map引用虽然指向了新的Map,但是旧的Map如果回收不及时,会造成内存溢出。

    为什么要使用COW ?

    java util 下的集合类都不能应付并发的修改和添加,比如在迭代集合的时候对此集合进行删除,

    则会出现 ConcurrentModificationException异常,或者 多个线程并发的添加,

    会出现 上一个添加的值被下一个值覆盖。

    为了应付并发的修改,有以下两种办法

    1、写时复制

    2、线程安全的容器

    比如: ArrayList --> CopyOnWriteList

    HashSet --> CopyOnWriteSet

    HashMap --> ConcurrentHashMap

    展开全文
  • 当然应用要实现读写分离,首先数据库层要先做到主从配置,本人前一篇文章介绍了mysql数据库的主从配置方式即:《mysql数据库主从配置》。应用实现读写分离至少有两种方法:应用本身通过代码实现,例如基于动态数据源...

    随着应用的访问量并发量的增加,应用读写分离是很有必要的。当然应用要实现读写分离,首先数据库层要先做到主从配置,本人前一篇文章介绍了mysql数据库的主从配置方式即:《mysql数据库主从配置》。

    应用实现读写分离至少有两种方法:

    • 应用本身通过代码实现,例如基于动态数据源、AOP的原理来实现写操作时用主数据库,读操作时用从数据库。
    • 通过中间件的方式实现,例如通过Mycat,即中间件会分析对应的SQL,写操作时会连接主数据库,读操作时连接从数据库。

    本篇文章是介绍通过Mycat中间件的方式实现读写分离。

    1、Mycat

    Mycat是一款开源的数据库中间件,其官网为http://www.mycat.io/,其中官方对它介绍为:

    Mycat 是一个强大的数据库中间件,不仅仅可以用作读写分离、以及分表分库、容灾备份,而且可以用于多租户应用开发、云平台基础设施、让你的架构具备很强的适应性和灵活性,借助于即将发布的Mycat 智能优化模块,系统的数据访问瓶颈和热点一目了然,根据这些统计分析数据,你可以自动或手工调整后端存储,将不同的表映射到不同存储引擎上,而整个应用的代码一行也不用改变。

    Mycat的实现原理为:

    Mycat 的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL 语句,首先对SQL 语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL 发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户。

    关于Mycat更多的介绍大家可以查看官网。

    2、部署Mycat

    应用是直接连接Mycat,然后Mycat管理了1个主数据库和1个从数据库,架构如下:

    f3f1f5ea8ef9ec3ab6a4980cd32b5fe1.png

    其中每个组件对应服务器地址为:

    • Mycat:192.168.197.131
    • 主库:192.168.197.135
    • 从库:192.168.197.136

    注意:对于mysql的主从配置方式请参考《mysql数据库主从配置》。

    部署Mycat步骤为:

    (1)、安装JDK,由于Mycat是基于Java语言来编写的,所以需要安装JDK,版本为1.8即可。

    JDK安装包可以到官网下载,下载后解压,然后配置环境变量,即:

    在/etc/profile文件中加入

    export JAVA_HOME=/opt/jdk1.8.0_112export PATH=$JAVA_HOME/bin:$PATH

    (2)、下载Mycat安装包,版本为1.6-RELEASE,下载地址为http://dl.mycat.io/1.6-RELEASE/,选择linux环境的版本即可。

    (3)、将Mycat安装包上传服务器后解压,即:

    tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz

    以上3步就相当于将Mycat部署好了,现在就需要配置Mycat了。

    配置Mycat步骤为:

    (1)、在主库和从库中分别创建用于Mycat连接的账号,即:

    GRANT CREATE,DELETE,INSERT,SELECT,UPDATE ON jgyw.* TO 'jgywuser'@'192.168.197.131' IDENTIFIED BY 'jgyw@123';

    以上语句的意思是创建一个jgywuser用户,该用户只有对jgyw模式下的表有增删改查的权限。

    (2)、配置Mycat的schema.xml文件,该文件位于Mycat中conf文件夹下,配置如下:

    ​ ​ ​ select user()

    其中:

    • schema 标签用于定义MyCat 实例中的逻辑库,MyCat 可以有多个逻辑库,每个逻辑库都有自己的相关配置。可以使用schema 标签来划分这些不同的逻辑库。
    • dataNode 标签定义了MyCat 中的数据节点,也就是我们通常说所的数据分片。一个dataNode 标签就是一个独立的数据分片。
    • dataHost标签直接定义了具体的数据库实例、读写分离配置和心跳语句。其中有几个重要的属性:
    balance属性负载均衡类型,目前的取值有3 种:balance="0
    展开全文
  • 实现读写分离需要更改两个配置文件Schema.xml和Server.xml文件Schema.xml文件的修改重要的属性设置1.schema 的name属性:用于设置在MyCat中显示的虚拟库的名称2.table:设置表的有几个表就会有几个table标签3.table ...

    实现读写分离需要更改两个配置文件

    • Schema.xml和Server.xml文件
        • Schema.xml文件的修改

    3e6cf451d7d55fe3cd77115b043f31e5.png

    重要的属性设置

        • 1.schema 的name属性:用于设置在MyCat中显示的虚拟库的名称
        • 2.table:设置表的有几个表就会有几个table标签
        • 3.table name:要和物理存在的表的名称一致
        • 4.dataNode name 为table引用,dataHost引用dataHost标签 database 物理数据库真是映射的数据库名称
    <?xml version="1.0"?>
    <!DOCTYPE mycat:schema SYSTEM "schema.dtd">
    <mycat:schema xmlns:mycat="http://io.mycat/">
    
    	<schema name="suibian" checkSQLschema="false" sqlMaxLimit="100">
    		<table name="t_user" dataNode="dn1"/>
    	</schema>
    
    	<dataNode name="dn1" dataHost="localhost1" database="demo1" />
    
    	<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
    		<heartbeat>select user()</heartbeat>
    		<writeHost host="hostM1" url="192.168.177.128:3306" user="root"
    		password="root">
    			<readHost host="hostS2" url="192.168.177.131:3306" user="root" 
    			password="root"/>
    		</writeHost>
    	</dataHost>
    </mycat:schema>

    Server.xml文件的配置

    5816ffb764fd27529c74daf96bcd5584.png
    <user name="root">
    		<property name="password">123456</property>
    		<property name="schemas">TESTDB</property>
    		
    		<!-- 表级 DML 权限设置 -->
    		<!-- 		
    		<privileges check="false">
    			<schema name="TESTDB" dml="0110" >
    				<table name="tb01" dml="0000"></table>
    				<table name="tb02" dml="1111"></table>
    			</schema>
    		</privileges>		
    		 -->
    	</user>
    
    	<user name="user">
    		<property name="password">user</property>
    		<property name="schemas">TESTDB</property>
    		<property name="readOnly">true</property>
    	</user>

    访问方式

    可以使用命令行访问或客户端软件访问.

    6.1.3.6 命令行访问方式

    mysql -u 用户名 -p 密码 -hmycat 主机 IP -P8066

    链接成功后,可以当做 MySQL 数据库使用.

    访问约束

    6.1.3.7 查看 Mycat 日志

    logs/wrapper.log

    日志中记录的是所有的 mycat 操作. 查看的时候主要看异常信息 caused by 信息

    6.1.3.8 balance(重点属性)

    balance=”0”, 不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上

    推荐选择:balance=”1”,全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡

    balance=”2”,所有读操作都随机的在 writeHost、 readhost 上分发。

    balance=”3”, 所有读请求随机的分发到 writeHost 对应的 readhost 执行,writerHost

    不负担读压力

    e36899de95bcb65377020dbb6cf8cf55.png
    展开全文
  • MySQL读写分离有好几种方式1、MySQL中间件2、MySQL驱动层3、代码控制关于中间件和驱动层的方式这里不做深究 ,暂且简单介绍下如何通过PHP代码来控制MySQL读写分离。我们都知道 “读” 在SQL语句里是 “SELECT”, ”...
  • mysql5.7使用ProxySQL实现读写分离ProxySql是mysql的一款中间件产品,是灵活强大的mysql代理层,可以实现读写分离,支持query路由功能,支持动态指定某个sql进行缓存,支持动态加载配置。故障切换和一些sql过滤功能...
  • 上篇文章中,在两个 windows 系统的电脑上安装了最新版8.0.21 MySQL 数据库,并且配置了主从。MySQL如何配置读写分离?主从复制的原理思想也很简单,就是从库不断地同步主库的改动...主从复制实现读写分离最大的缺点...
  • 分享给大家供大家参考,具体如下:当前服务器只做了主从,未配置读写分离,读写分离的功能就只有交给程序来实现,这里主要谈谈Codeigniter怎么实现读写分离,并且需要满足以下两点:1、读写分离对开发应该透明。...
  • 主从复制的原理思想也很简单...主从复制实现读写分离最大的缺点就是从库同步到主库的数据存在延迟,网络不好的时候,延迟比较严重。如何实现读写分离?在我们平时开发中,一般不会自己去控制 select 请求从从库拿 C...
  • 当前服务器只做了主从,未配置读写分离,读写分离的功能就只有交给程序来实现,本文主要谈谈Codeigniter怎么实现读写分离,并且需要满足以下两点: 1、读写分离对开发应该透明。 网上有方案通过手动load多个DB来...
  • 如果你能对项目中使用多个数据库进行读写分离的话,那么将大大提高你项目的性能。而Django自带的机制也对此提供了支持。我们可以简单的操作一下。(当然数据库的主从同步设置还是需要运维同志的协助。)修改配置文件...
  • 为什么要使用读写分离读写分离是互联网公司常用的技术方案,用来分摊数据库压力的。我们知道在一般的互联网项目中都是读多写少,这就导致数据库在大部分时候都在进行读操作,那么在高并发、高流量读的情况下,...
  • 当前服务器只做了主从,未配置读写分离,读写分离的功能就只有交给程序来实现,本文主要谈谈Codeigniter怎么实现读写分离,并且需要满足以下两点: 1、读写分离对开发应该透明。 网上有方案通过手动load多个DB来...
  • 前段时间有项目有读写分离的需要,因此完成了该类库mybatis-read-write-split来实现读写分离。它支持两种模式的主备分离:业务透明的读写分离。自动解析sql的读写类型并进行路由转发。基于注解的读写分离。通过注解...
  • 通过读写分离,可以实现读锁和写锁的竞争。读锁和写锁可以具体网上找其他资源了解。怎么做?1. 主从复制:主数据库有写操作,从数据库自动同步。从数据库通过I/O线程去请求主数据库的binlog日志文件(二进制日志,...
  • 当前服务器只做了主从,未配置读写分离,读写分离的功能就只有交给程序来实现,这里主要谈谈Codeigniter怎么实现读写分离,并且需要满足以下两点: 1、读写分离对开发应该透明。 网上有方案通过手动load多个DB来实现...
  • 怎么实现呢?请往下看!5进阶:实现从库的负载均衡 请看到我们定义的从库创建实例部分代码,已经增加了选择查询数据库连接的策略;如图15: 图15 其实我们还可以增加另外的一些策略:比方说轮询策略,如果有十个从库...
  • MYSQL主从配置以及客户端代码实现读写分离功能1.主从配置环境描述:主数据库服务器IP:172.16.48.52版本:MYSQL5.1.73系统:CentOS6.5安装方式:源码安装[root@Jack-PC ~]# mysql -u root -pEnter password:Welcome ...
  • 等,数据库层今天先不讨论,那么今天我们就来看看怎么在应用层实现读写分离。框架:laravel5.7说明:Laravel默认将 select 的语句让 read 指定的数据库执行,insert/update/delete 则交给 write 指定的数据库,达到...
  • mysql-proxy实现读写分离MySQL Proxy是一个处于你的client端和MySQL server端之间的简单程序,它可以监测、分析或改变它们的通信。它使用灵活,没有限制,常见的用途包括:负载平衡,故障、查询分析,查询过滤和修改...
  • 读写分离怎么做,怎么实现

    千次阅读 2019-12-13 00:07:34
    实现方案: # #第一种是在应用层做 方案就是根据我们的不同的sql语句来选择不同的数据源来操作,优点是对性能的损耗比较小,缺点是强依赖程序员。如果是是新开发程序还好。如果是改造原有的系统,就会变的及其...
  • 1.mysql如何配置读写分离: Mysql主从配置,实现读写分离(转载)http://www.cnblogs.com/alvin_xp/p/4162249.html 2.开发项目中实际怎么应用读写分离:
  • 推荐阅读:数据库索引原理及优化,这篇文章看完你还不懂就来找我MySQL数据库一知半解?阿里架构师写得高性能MySQL文档你不能错过为什么需要读写分离至于为什么...顺便也可以了解一下怎么通过代码进行读写分离的MySQ...
  • 这篇文章主要介绍了Django连接数据库并实现读写分离过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下前言当一个项目当中有大量的数据的时候,你所有的IO...
  • spring集成mybatis实现mysql读写分离,简单介绍了通过 Spring AOP 从应用程序层面实现读写分离;读写分离效果是达到了,可我们知道为什么那么做就能实现读写分离吗 ?知道的请快点走开 接下来请好好欣赏我的表演...
  • 近日工作任务较轻,有空学习学习技术,遂来研究如果实现读写分离。这里用博客记录下过程,一方面可备日后查看,同时也能分享给大家(网上的资料真的大都是抄来抄去,,还不带格式的,看的真心难受)。下面话不多说了,...
  • 主从复制为一个数据提供多个副本 ,扩展了redis的一个读的性能 可以读写分离 1.一个master 可以有多个slave 2.一个slave 只能由一个master 实现主从复制的两种方式: 1.slaveof 命令 2.通过配置 测试: 新增...
  • sql中怎么实现真正的读写分离,就是用上面的订阅发布吗,数据量很大的话同步时间怎么保证
  • MYSQL 之 读写分离

    2020-01-09 15:44:22
    文章目录一、读写分离的概述1.1、读写分离的基本原理二、怎么实现读写分离?2.1、环境准备和安装包2.2、实验操作 一、读写分离的概述 读写分离是高性能数据库集群的一种方式,其本质是将访问压力分散到集群中的...

空空如也

空空如也

1 2 3 4 5 ... 16
收藏数 315
精华内容 126
关键字:

怎么实现读写分离