精华内容
下载资源
问答
  • 通过结合帐号、应用和数据库三元组,分布式数据服务对属于不同的应用的数据进行隔离,保证不同应用之间的数据不能通过分布式数据服务互相访问。在通过可信认证的设备间,分布式数据服务支持应用数据相互同步,为用户...

    一、简介

    ① 基本概念
    • 分布式数据服务(Distributed Data Service,DDS) 为应用程序提供不同设备间数据库数据分布式的能力。通过调用分布式数据接口,应用程序将数据保存到分布式数据库中。通过结合帐号、应用和数据库三元组,分布式数据服务对属于不同的应用的数据进行隔离,保证不同应用之间的数据不能通过分布式数据服务互相访问。在通过可信认证的设备间,分布式数据服务支持应用数据相互同步,为用户提供在多种终端设备上一致的数据访问体验。
    • KV 数据模型:
      • “KV数据模型”是“Key-Value数据模型”的简称,“Key-Value”即“键-值”。它是一种 NoSQL 类型数据库,其数据以键值对的形式进行组织、索引和存储。
      • KV 数据模型适合不涉及过多数据关系和业务关系的业务数据存储,比 SQL 数据库存储拥有更好的读写性能,同时因在分布式场景中降低了数据库版本兼容和数据同步过程中冲突解决的复杂度而被广泛使用。分布式数据库也是基于 KV 数据模型,对外提供 KV 类型的访问接口。
    • 分布式数据库事务性:分布式数据库事务支持本地事务(和传统数据库的事务概念一致)和同步事务,同步事务是指在设备之间同步数据时,是以本地事务为单位进行同步,一次本地事务的修改要么都同步成功,要么都同步失败。
    • 分布式数据库一致性:在分布式场景中一般会涉及多个设备,组网内设备之间看到的数据是否一致称为分布式数据库的一致性。分布式数据库一致性可以分为强一致性、弱一致性和最终一致性。
      • 强一致性:是指某一设备成功增、删、改数据后,组网内设备对该数据的读取操作都将得到更新后的值。
      • 弱一致性:是指某一设备成功增、删、改数据后,组网内设备可能能读取到本次更新数据,也可能读取不到,不能保证在多长时间后每个设备的数据一定是一致的。
      • 最终一致性:是指某一设备成功增、删、改数据后,组网内设备可能读取不到本次更新数据,但在某个时间窗口之后组网内设备的数据能够达到一致状态。
      • 强一致性对分布式数据的管理要求非常高,在服务器的分布式场景可能会遇到。因为移动终端设备的不常在线、以及无中心的特性,分布式数据服务不支持强一致,只支持最终一致性。
    • 分布式数据库同步
      • 底层通信组件完成设备发现和认证,会通知上层应用程序(包括分布式数据服务)设备上线。收到设备上线的消息后分布式数据服务可以在两个设备之间建立加密的数据传输通道,利用该通道在两个设备之间进行数据同步。
      • 分布式数据服务提供了两种同步模式:手动同步和自动同步模式。手动同步模式完全由应用程序调用接口来触发,并且支持指定同步的设备列表和同步模式(PULL、 PUSH 和 PULL_PUSH 三种同步模式)。自动同步模式由分布式数据库来完成数据同步(同步时机包括设备上线、应用程序修改数据等),业务不感知同步操作。
    • 单版本分布式数据库:单版本是指数据在本地保存是以单个 KV 条目为单位的方式保存,对每个 Key 最多只保存一个条目项,当数据在本地被用户修改时,不管它是否已经被同步出去,均直接在这个条目上进行修改。同步也以此为基础,按照它在本地被写入或更改的顺序将当前最新一次修改逐条同步至远端设备。
    • 设备协同分布式数据库:设备协同分布式数据库建立在单版本分布式数据库之上,对应用程序存入的 KV 数据中的 Key 前面拼接了本设备的 DeviceID 标识符,这样能保证每个设备产生的数据严格隔离,底层按照设备的维度管理这些数据,设备协同分布式数据库支持以设备的维度查询分布式数据,但是不支持修改远端设备同步过来的数据。
    • 分布式数据库冲突解决策略:分布式数据库多设备提交冲突场景,在给提交冲突做合并的过程中,如果多个设备同时修改了同一数据,则称这种场景为数据冲突。数据冲突采用默认冲突解决策略,基于提交时间戳,取时间戳较大的提交数据,当前不支持定制冲突解决策略。
    • 数据库 Schema 化管理与谓词查询:单版本数据库支持在创建和打开数据库时指定Schema,数据库根据 Schema 定义感知 KV 记录的 Value 格式,以实现对 Value 值结构的检查,并基于 Value 中的字段实现索引建立和支持谓词查询。
    • 分布式数据库备份能力:提供分布式数据库备份能力,业务通过设置 backup 属性为 true,可以触发分布式数据服务每日备份。当分布式数据库发生损坏,分布式数据服务会删除损坏数据库,并且从备份数据库中恢复上次备份的数据。如果不存在备份数据库,则创建一个新的数据库。同时支持加密数据库的备份能力。
    ② 运作机制
    • 分布式数据服务支撑 HarmonyOS 系统上应用程序数据库数据分布式管理,支持数据在相同帐号的多端设备之间相互同步,为用户在多端设备上提供一致的用户体验,分布式数据服务包含五部分:
      • 服务接口:分布式数据服务提供专门的数据库创建、数据访问、数据订阅等接口给应用程序调用,接口支持 KV 数据模型,支持常用的数据类型,同时确保接口的兼容性、易用性和可发布性。
      • 服务组件:服务组件负责服务内元数据管理、权限管理、加密管理、备份和恢复管理以及多用户管理等、同时负责初始化底层分布式 DB 的存储组件、同步组件和通信适配层。
      • 存储组件:存储组件负责数据的访问、数据的缩减、事务、快照、数据库加密,以及数据合并和冲突解决等特性。
      • 同步组件:同步组件连结了存储组件与通信组件,其目标是保持在线设备间的数据库数据一致性,包括将本地产生的未同步数据同步给其他设备,接收来自其他设备发送过来的数据,并合并到本地设备中。
      • 通信适配层:通信适配层负责调用底层公共通信层的接口完成通信管道的创建、连接,接收设备上下线消息,维护已连接和断开设备列表的元数据,同时将设备上下线信息发送给上层同步组件,同步组件维护连接的设备列表,同步数据时根据该列表,调用通信适配层的接口将数据封装并发送给连接的设备。
    • 应用程序通过调用分布式数据服务接口实现分布式数据库创建、访问、订阅功能,服务接口通过操作服务组件提供的能力,将数据存储至存储组件,存储组件调用同步组件实现将数据同步,同步组件使用通信适配层将数据同步至远端设备,远端设备通过同步组件接收数据,并更新至本端存储组件,通过服务接口提供给应用程序使用。
    • 数据分布式运作示意图如下:

    在这里插入图片描述

    ③ 使用限制
    • 应用程序如需使用分布式数据服务完整功能,需要申请 ohos.permission.DISTRIBUTED_DATASYNC 权限。
    • 分布式数据服务的数据模型仅支持 KV 数据模型,不支持外键、触发器等关系型数据库中的技术点。
    • 分布式数据服务支持的 KV 数据模型规格:
      • 设备协同数据库,Key 最大支持 896Byte,Value 最大支持 4MB - 1Byte。
      • 单版本数据库,Key 最大支持 1KB,Value 最大支持 4MB - 1Byte。
      • 每个应用程序最多支持同时打开 16 个 KvStore。
    • 由于支持的存储类型不完全相同等原因,分布式数据服务无法完全代替业务沙箱内数据库数据的存储功能,开发人员需要确定要做分布式同步的数据,把这些数据保存到分布式数据服务中。
    • 分布式数据服务当前不支持应用程序自定义冲突解决策略。
    • 分布式数据服务当前流控机制针对 KvStore 的接口 1 秒最大访问 1000 次,1 分钟最大访问 10000 次。KvManager 的接口 1 秒最大访问 50 次,1 分钟最大访问 500 次。
    • 如果需要在分布式数据库事件回调的方法里修改 UI 组件,建议使用 UITaskDispatcher 机制。
    ④ 应用场景
    • 分布式数据服务主要实现对用户设备中应用程序的数据内容的分布式同步。
    • 当设备 1 上的应用 A 在分布式数据库中增、删、改数据后,设备 2 上的应用 A 也可以获取到该数据库变化。可在分布式图库、信息、通讯录、文件管理器等场景中使用。

    二、分布式数据服务 API

    • HarmonyOS 系统中的分布式数据服务模块为开发者提供下面几种功能:
    功能分类 接口名称 描述
    分布式数据库创建、打开、关闭和删除 isCreateIfMissing() 检查数据库不存在时是否创建
    setCreateIfMissing(boolean isCreateIfMissing) 设置数据库不存在时是否创建
    isEncrypt() 获取数据库是否加密
    setEncrypt(boolean isEncrypt) 设置数据库是否加密
    getStoreType() 获取分布式数据库的类型
    setStoreType(KvStoreType storeType) 设置分布式数据库的类型
    KvStoreType.DEVICE_COLLABORATION 设备协同分布式数据库类型
    KvStoreType.SINGLE_VERSION 单版本分布式数据库类型
    getKvStore(Options options, String storeId) 根据Options配置创建和打开标识符为storeId的分布式数据库
    closeKvStore(KvStore kvStore) 关闭分布式数据库
    deleteKvStore(String storeId) 删除分布式数据库
    分布式数据增、删、改、查 getStoreId() 根据配置构造帐号键值数据库管理类实例
    putBoolean(String key, boolean value)
    putInt(String key, int value)
    putFloat(String key, float value)
    putDouble(String key, double value)
    putString(String key, String value)
    putByteArray(String key, byte[] value)
    putBatch(List entries)
    插入和更新数据
    delete(String key)
    deleteBatch(List keys)
    删除数据
    getInt(String key)
    getFloat(String key)
    getDouble(String key)
    getString(String key)
    getByteArray(String key)
    getEntries(String keyPrefix)
    查询数据
    分布式数据谓词查询 select()
    reset()
    equalTo(String field, int value)
    equalTo(String field, long value)
    equalTo(String field, double value)
    equalTo(String field, String value)
    equalTo(String field, boolean value)
    notEqualTo(String field, int value)
    notEqualTog(String field, long value)
    notEqualTo(String field, boolean value)
    notEqualTo(String field, String value)
    notEqualTo(String field, double value)
    greaterThan(String field, int value)
    greaterThan(String field, long value)
    greaterThan(String field, double value)
    greaterThan(String field, String value)
    lessThan(String field, int value)
    lessThan(String field, long value)
    lessThan(String field, double value)
    lessThan(String field, String value)
    greaterThanOrEqualTo(String field, int value)
    greaterThanOrEqualTo(String field, long value)
    greaterThanOrEqualTo(String field, double value)
    greaterThanOrEqualTo(String field, String value)
    lessThanOrEqualTo(String field, int value)
    lessThanOrEqualTo(String field, long value)
    lessThanOrEqualTo(String field, double value)
    lessThanOrEqualTo(String field, String value)
    isNull(String field)
    orderByDesc(String field)
    orderByAsc(String field)
    limit(int number, int offset)
    like(String field, String value)
    unlike(String field, String value)
    inInt(String field, List valueList)
    inLong(String field, List valueList)
    inDouble(String field, List valueList)
    inString(String field, List valueList)
    notInInt(String field, List valueList)
    notInLong(String field, List valueList)
    notInDouble(String field, List valueList)
    notInString(String field, List valueList)
    and()
    or()
    对于Schema数据库谓词查询数据
    订阅分布式数据变化 subscribe(SubscribeType subscribeType, KvStoreObserver observer) 订阅数据库中数据的变化
    分布式数据同步 sync(List deviceIdList, SyncMode mode) 在手动模式下,触发数据库同步

    三、分布式数据服务使用流程

    ① 根据配置构造分布式数据库管理类实例
    • 根据应用上下文创建 KvManagerConfig 对象。
    • 创建分布式数据库管理器实例。
    • 以下为创建分布式数据库管理器的代码示例:
    	Context context;
    	...
    	KvManagerConfig config = new KvManagerConfig(context);
    	KvManager kvManager = KvManagerFactory.getInstance().createKvManager(config);
    
    ② 获取/创建单版本分布式数据库
    • 声明需要创建的单版本分布式数据库 ID 描述。
    • 创建单版本分布式数据库,跨设备自动同步数据库功能默认开启。
    • 以下为创建单版本分布式数据库的代码示例:
    	Options CREATE = new Options();
    	
    	CREATE.setCreateIfMissing(true).setEncrypt(false).setKvStoreType(KvStoreType.SINGLE_VERSION);
    	String storeID = "testApp";
    	SingleKvStore singleKvStore = kvManager.getKvStore(CREATE, storeID);
    
    ③ 订阅分布式数据变化
    • 客户端需要实现 KvStoreObserver 接口。
    • 构造并注册 KvStoreObserver 实例。
    • 以下为订阅单版本分布式数据库所有(本地及远端)数据变化通知的代码示例:
    	class KvStoreObserverClient implements KvStoreObserver {
    	    @Override
    	    public void onChange(ChangeNotification notification) {
    	        List<Entry> insertEntries = notification.getInsertEntries();
    	        List<Entry> updateEntries = notification.getUpdateEntries();
    	        List<Entry> deleteEntries = notification.getDeleteEntries();
    	
    	    }
    	}
    	
    	KvStoreObserver kvStoreObserverClient = new KvStoreObserverClient();
    	singleKvStore.subscribe(SubscribeType.SUBSCRIBE_TYPE_ALL, kvStoreObserverClient);
    
    ④ 将数据写入单版本分布式数据库
    • 构造需要写入单版本分布式数据库的 Key(键)和 Value(值)。
    • 将键值数据写入单版本分布式数据库。
    • 以下为将字符串类型键值数据写入单版本分布式数据库的代码示例:
    	String key = "todayWeather";
    	String value = "Sunny";
    	singleKvStore.putString(key, value);
    
    ⑤ 查询单版本分布式数据库数据
    • 构造需要从单版本分布式数据库快照中查询的 Key(键)。
    • 从单版本分布式数据库快照中获取数据。
    • 以下为从单版本分布式数据库中查询字符串类型数据的代码示例:
    	String key = "todayWeather";
    	String value = singleKvStore.getString(key);
    
    ⑥ 同步数据到其他设备
    • 获取已连接的设备列表。
    • 选择同步方式进行数据同步。
    • 以下为单版本分布式数据库进行数据同步的代码示例,其中同步方式为 PUSH_ONLY:
    	List<DeviceInfo> deviceInfoList = kvManager.getConnectedDevicesInfo(DeviceFilterStrategy.NO_FILTER);
    	List<String> deviceIdList = new ArrayList<>();
    	for (DeviceInfo deviceInfo : deviceInfoList) {
    	    deviceIdList.add(deviceInfo.getId());
    	}
    	singleKvStore.sync(deviceIdList, SyncMode.PUSH_ONLY);
    
    ⑦ 关闭单版本分布式数据库
    • 以下为关闭单版本分布式数据库的代码示例:
    	kvManager.closeKvStore(singleKvStore);
    
    ⑧ 删除单版本分布式数据库
    • 以下为删除单版本分布式数据库的代码示例:
    	kvManager.deleteKvStore(storeID);
    
    展开全文
  • 分布式数据存储

    千次阅读 2019-08-19 09:37:58
    分布式存储概念 存储方式的演进 [1] 直连式存储DAS [2] 集中式存储NAS 、SAN等 分布式存储 基本架构 [1] 有中心管理节点,存储节点有主从 [2] 有中心管理节点,存储节点无主从 分布式系统存储指标

    分布式存储概念

    • 分布式存储就是一种数据存储技术,通过Internet使用每台机器上的硬盘空间,并将并将这些分散的存储资源构成一个虚拟的存储设备,数据分散的存储在企业的各个角落。“分布式”指带了一种独特的系统架构类型 ,这种系统架构是由一组通过网络进行通信,为了完成共同的任务而协调工作的计算机节点组成

    存储方式的演进

    • [1] 直连式存储DAS(Direct-Attached Storage),是一种常见的存储形式,特别是在规模较小的企业中。由于企业本身数据量都不大,基本都采用高密度的存储服务器或者服务器后接JBOD等形式,这种形式的存储属于DAS架构。(PC中的硬盘或只有一个外部SCSI接口的JBOD都属于DAS架构)
      优点:方便,节省投资
      缺点:备份困难,服务器故障,数据不可访问,服务器易成为瓶颈
      在这里插入图片描述

    • [2] 集中式存储NAS 、SAN等

      SAN(Storage Area Network)存储,即存储区域网络,这个是通过某种交换机连接存储阵列和服务器主机等设备,形成一个专用的网络。 iSCSI,基于以太网的SAN存储形式,这种存储形式其实是利用TCP/IP协议实现了对SCSI协议的封装。
      优点:随着存储容量的增长,SAN允许企业独立地增加他们的存储容量。适用于大型数据或数据库系统
      缺点:成本高,较为复杂

      NAS(Network Attached Storage)即网络存储设备,是文件级的存储方法,就是一台在网络上提供文档共享服务的网络存储服务器,多用来进行文件共享。用于存储非数据化数据。
      优点:具有一定扩展性,连接网络
      缺点:能力有限
      在这里插入图片描述

    分布式存储

    主要包括分布式软件和标准服务器。分布式网络存储系统采用可扩展的系统结构,利用多台存储服务器分担存储负荷,利用位置服务器定位存储信息,不但提高了系统的可靠性,可用性和存储效率,还易于扩展
    在这里插入图片描述

    基本架构

    • [1] 有中心管理节点,存储节点有主从
      在这里插入图片描述

    • Master节点:在由中心控制节点的分布式文件系统,从哪里读写的任务基本是有中心控制节点完成的,为了完成这项核心的任务,Master节点需要做三件较重要的事情——①存储节点信息和状态②文件读写的调度策略③存储节点选主在这里插入图片描述

    • StorageNode节点:数据节点除了负责文件在单机系统上如何进行存储,对于有主从之分的存储节点,各自还承担如何保持备份数据一致性的任务——①单机存储引擎的实现②保证备份一致性③汇报消息,听从调度在这里插入图片描述
      在这里插入图片描述

    • Client节点:一般作为分布式文件系统的接入层,对于写操作,接受用户数据流,将数据写入存储节点,对于该操作,从多副本中随机选择副本来写
      在这里插入图片描述

    • [2] 无中心管理节点,存储节点无主从

    • ProxyServer节点:由以下几个组件组成:

    • Object Server单机的存储引擎实现

    • Object Replicator确保副本数量和位置的正确性及一致性

    • Object Auditor检测副本数据是否正确

    • Object Updater解决对象存储的元数据的更新问题

    • 这里附上一篇知乎上对该内容较为详细的理解
      基本框架图
      Swift基本框架图

    分布式系统存储指标

    • 持久性:一段时间内保持数据不丢失的能力
    • 一致性:当一个对象的Value被修改后需要等待多久客户端才能“看到”这个修改
    • 可用性:强调能否成功的读写,看重的是过程
    • 延迟:从开始点到结束点所花费的时间差,包括读延迟和写延迟
    • 带宽:吞吐率,分为读带宽和写带宽
    • 空间利用率:存储单位有效数据需要占用多少介质空间,就是存储IGB数据需要占用多少GB的裸盘空间
    • 可扩展性:通过增减硬件来调节存储系统某些方面指标的能力
    展开全文
  • springmvcmybatis多数据分布式事务管理 pom依赖 jtaproperties 配置数据源 配置SQLSessionFactory 配置MapperScanner 配置Jta事务 实体 dao XML service Junit测试 完结springmvc+mybatis多数据分布式事务管理 ...

    目录

    springmvc+mybatis多数据源分布式事务管理

        最近项目用到spring多数据源以进行数据整合,可是配置上事务时,发现数据源不能进行切换,
    原因是因为事务是在connection层面管理的,启用事务后,一个事务内部的connection是复用的,
    所以就算AOP切了数据源字符串,但是数据源并不会被真正修改,所以决定使用atomikos进行分布式事务的管理。
    

    pom依赖

    <dependency>
        <groupId>com.atomikos</groupId>
        <artifactId>transactions-jdbc</artifactId>
        <version>3.9.1</version>
    </dependency>
    <dependency>
        <groupId>javax.transaction</groupId>
        <artifactId>jta</artifactId>
        <version>1.1</version>
    </dependency>
    <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib-nodep</artifactId>
        <version>3.2.4</version>
    </dependency>

    jta.properties

    把此配置文件放入classpath路径 项目启动会自动加载 不需进行配置
    
    com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
    com.atomikos.icatch.console_file_name = tm.out   
    com.atomikos.icatch.log_base_name = tmlog   
    com.atomikos.icatch.tm_unique_name = com.atomikos.spring.jdbc.tm   
    com.atomikos.icatch.console_log_level = INFO  

    配置数据源

        为了测试这里配置2个数据源,大家可按自己项目情况配置。
    
    <property name="uniqueResourceName" value="ds1"/>
        注意当配置多个数据源时uniqueResourceName的value不能重复
    
    <bean id="dataSource1" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-               method="init" destroy-method="close">
        <property name="uniqueResourceName" value="ds1"/>
        <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
        <property name="xaProperties">
            <props>
                <prop key="url">jdbc:mysql://localhost/test</prop>
                <prop key="user">root</prop>
                <prop key="password">123456</prop>
            </props>
        </property>
        <property name="minPoolSize" value="10" />
        <property name="maxPoolSize" value="100" />
        <property name="borrowConnectionTimeout" value="30" />
        <property name="testQuery" value="select 1" />
        <property name="maintenanceInterval" value="60" />
    </bean>
    
    <bean id="dataSource2" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
        <property name="uniqueResourceName" value="ds2"/>
        <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/>
        <property name="xaProperties">
            <props>
                <prop key="url">jdbc:mysql://localhost/smart-sso</prop>
                <prop key="user">root</prop>
                <prop key="password">123456</prop>
            </props>
        </property>
        <property name="minPoolSize" value="10" />
        <property name="maxPoolSize" value="100" />
        <property name="borrowConnectionTimeout" value="30" />
        <property name="testQuery" value="select 1" />
        <property name="maintenanceInterval" value="60" />
    </bean>

    配置SQLSessionFactory

        指定mapper文件和实体所在路径
    
    <bean id="sqlSessionFactory1" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource1"/>
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
        <property name="typeAliasesPackage" value="com.fk.entity"/>
    </bean>
    <bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource2"/>
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
        <property name="typeAliasesPackage" value="com.fk.entity"/>
    </bean>

    配置MapperScanner

        指定dao文件所在包 并指定所用SQlSessionFactory
    
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.fk.mapperOne" />
        <property name="sqlSessionFactory" ref="sqlSessionFactory1"/>
    </bean>
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.fk.mapperTwo" />
        <property name="sqlSessionFactory" ref="sqlSessionFactory2"/>
    </bean>

    配置Jta事务

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager">
            <bean class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close">
                <property name="forceShutdown" value="true"/>
            </bean>
        </property>
        <property name="userTransaction">
            <bean class="com.atomikos.icatch.jta.UserTransactionImp"/>
        </property>
    </bean>
        最后加上声明式注解支持
    
        <tx:annotation-driven/>
        数据源和事务配置已经完成,接下来就是测试分布式事务是否可用了。
    

    实体

    为了测试方便 这里2个数据源使用的是一个实体
    
    public class Student {
        private Integer id;
        private String name;
        private Integer age;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    }

    dao

        这里两个mapper分别在配置MapperScanner配置的包体里
    
    package com.fk.mapperOne;
    
    import com.fk.entity.Student;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface StudentOneMapper {
        void insert(Student student);
    }
    package com.fk.mapperTwo;
    
    import com.fk.entity.Student;
    import org.springframework.stereotype.Repository;
    
    @Repository
    public interface StudentTwoMapper {
        void insert(Student student);
    }

    XML

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.fk.mapperOne.StudentOneMapper" >
        <insert id="insert" parameterType="com.fk.entity.Student">
            insert into student(id,name,age) values (#{id},#{name},#{age})
        </insert>
    </mapper>
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.fk.mapperTwo.StudentTwoMapper" >
        <insert id="insert" parameterType="com.fk.entity.Student">
            insert into student(id,name,age) values (#{id},#{name},#{age})
        </insert>
    </mapper>

    service

    package com.fk.service;

    import com.fk.entity.Student;
    import com.fk.mapperOne.StudentOneMapper;
    import com.fk.mapperTwo.StudentTwoMapper;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;

    @Service
    public class StudentServiceImpl {

    @Autowired
    private StudentOneMapper studentOneMapper;
    
    @Autowired
    private StudentTwoMapper studentTwoMapper;
    
    @Transactional
    public void insert() throws Exception{
        Student student = new Student();
        student.setId(1);
        student.setName("Nancy");
        student.setAge(12);
    
        studentOneMapper.insert(student);
    
        student = new Student();
        student.setId(1);
        student.setName("Tom");
        student.setAge(2);
        studentTwoMapper.insert(student);
    }
    

    }

    Junit测试

    接下来使用junit进行测试
    
    
    import com.fk.service.StudentServiceImpl;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "classpath:/spring/spring-mvc.xml",
            "classpath:/spring/spring-mybatis.xml"})
    public class StudentJunit {
    
        @Autowired
        private StudentServiceImpl studentService;
        @Test
        public void TestInsert(){
            try {
                studentService.insert();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    先测试下是否能插入数据
    

    这里写图片描述

    可以看到2个数据库里都已经插入一条数据
    
    接下来在测试下异常是否会回滚
    
    @Transactional
        public void insert() throws Exception{
            Student student = new Student();
            student.setId(2);
            student.setName("Nancy");
            student.setAge(12);
    
            studentOneMapper.insert(student);
    
            student = new Student();
            student.setId(1);
            student.setName("Tom");
            student.setAge(2);
            studentTwoMapper.insert(student);
        }
        将第一个插入实体的ID加1,保持第二个实体不变,因为表里有设置主键,这样第二条插入时,
    会出现主键重复异常,以此来测试第一条插入语句是否会回滚。
    

    这里写图片描述

    如我们所愿,主键重复,接下来看下数据是否有插入
    

    这里写图片描述

    yes!数据没有插入,则证明事务已回滚了。
    

    完结

    分布式事务的内容就是这些了,由于本人初次接触分布式事务,有不足之处还请谅解并指出,谢谢!
     [完整Demo](http://git.oschina.net/monsterjava/fk_demo/tree/feature_fk/)
    
    展开全文
  • 分布式数据存储与管理[HDFS+HBase]

    千次阅读 2018-05-29 11:18:31
    分布式数据存储与管理[HDFS+HBase] 一、系统架构 在分布式存储领域,相信大多数人对HDFS(Hadoop Distributed File System)并不陌生,它是GFS(Google File System)的开源实现版本,解决大规模非结构化数据...

    一、系统架构

    在分布式存储领域,相信大多数人对HDFS(Hadoop Distributed File System)并不陌生,它是GFS(Google File System)的开源实现版本,解决大规模非结构化数据存储的问题。然而,HBase则是基于HDFS之上的一个分布式的、面向列存的开源NoSQL数据库,解决大规模结构化和半结构化数据存储的问题。

    a) HDFS架构

    HDFS[1][2]采用Master/Slave架构。一个HDFS集群是由一个Namenode和一定数目的Datanodes组成,如图1所示。Namenode是一个中心服务器,负责管理文件系统的名字空间(namespace)以及客户端对文件的访问。集群中的Datanode一般是一个节点一个,负责管理它所在节点上的存储。HDFS暴露了文件系统的名字空间,用户能够以文件的形式在上面存储数据。从内部看,一个文件其实被分成一个或多个数据块,这些块存储在一组Datanode上。Namenode执行文件系统的名字空间操作,比如打开、关闭、重命名文件或目录。它也负责确定数据块到具体Datanode节点的映射。Datanode负责处理文件系统客户端的读写请求。在Namenode的统一调度下进行数据块的创建、删除和复制。

    这里写图片描述
    图1 HDFS系统架构

    b) HBase架构

    HBase[3][4][5]也同样采用Master/Slave架构。一个HBase集群是由一个HMaster和一定数目的RegionServer组成,如图2所示。HBase的一张表会被切分成若干块,每块叫做一个Region。每个Region中存储着从startKey到endKey中间的记录。这些Region会被分到集群的各个节点上去存储,每个节点叫做一个RegionServer,这些节点负责数据的读写,一个RegionServer可以处理大约1000个Regions。HMaster的功能是处理Region的协调工作,具体包括:管理RegionServer,实现其负载均衡;管理和分配Region,比如在Region Split时分配新的Region;在RegionServer退出时迁移其内的Region到其他RegionServer上;监控集群中所有RegionServer的状态(通过Heartbeat和监听ZooKeeper中的状态);处理Schema更新请求(创建、删除、修改Table的定义)。

    这里写图片描述
    图2 HBase系统架构

    有一个的特殊的HBase目录表,.META表,保存了集群中Regions的位置。HBase读写流程,如图3所示。

    这里写图片描述
    图3 HBase读写流程

    当客户端第一次读取(写入)HBase请求到达时:

    • 第一步:客户端从HMaster中获取.META表; 第二步:客户端将查询.META表来获取要访问的row
    • key对应的RegionServer,并将这些信息与.META表格一起缓存起来。
    • 第三步:将从相应的RegionServer获取该行(写入该行到相应的RegionServer。

    二、分析与对比

    HDFS+HBase与单机中的数据库+文件系统类似,但又不完全一样。首先,HBase不实现复制机制,而是交给底下的HDFS系统,HDFS则会把一个块写入到多个数据节点中。因此,HBase更像维护表格与文件之间映射关系的一个计算引擎。如果用Aurora或PolarDB中的描述方式,HBase是控制面(控制引擎),HDFS则是数据面(存储引擎),只不过这两种层级分布在不同的系统之中而已。其次,HBase与传统的关系型数据库对外接口不同,仅支持API接口,不支持SQL语言,也不支持Join等操作,也放松了ACID属性,所以,它是一个NoSQL型数据库。

    像HDFS+HBase这样分布式数据存储与管理系统,它们将控制和存储两大模块进行分层,分别在两个相对独立的分布式系统中实现。不难发现,这种实现方式既存在优点,也存在弊端。因为层次化的设计可以使整个系统的耦合度和复杂度降低,也可以使整个系统的每一个部分相对独立,也更具有通用性和一般性。然而,这样相对独立的设计也给整个系统带来许多不必要的开销,降低了系统的整体性能。在每一个独立的系统中,都有一整套Master/Slave架构,上一层系统充当下一层系统的Client端,这就使整个数据存储的路径变长了,例如,一次简单写操作要既经过HBase的Master也要经过HDFS的Master。随着越来越多的应用对低时延、高吞吐量特性的需求,这样的设计也就很难满足了。所以,整个系统就必须高度融合,尽可能减少不必要的网络和存储开销,使整个读/写路径变的更短,才使整系统的性能得以提升。换句话说,当前的HDFS+HBase软件栈太重了,我们必须将其减负才能实现低时延、高吞吐量的特性。

    如果我们换个角度看问题,HDFS+HBase其本质也是一种shared disk的架构,整个HBase集群共享下层HDFS存储池。相信大多数人已经对shared disk VS shared nothing问题[7][8]不言而喻了,就不再赘述了。除了上述问题以外,HBase采用列存储的方式,很难应对OLTP型的负载,并且它的数据恢复也采用WAL的方式,导致其恢复时间较长,也存在不可靠的分裂问题[6]。

    三、小结

    像HDFS+HBase这样,由多个独立的分布式系统组成的数据存储与管理解决方案,各个系统更具一般性和通用性,但是很难满足用户对更低时延、更高吞吐量的追求。为实现更高性能,整个系统之间必须高度融合,更具定制化,尽可能缩短数据处理的路径,从而减少不必要的开销。

    参考文献:

    [1] http://hadoop.apache.org/docs/r1.0.4/cn/hdfs_design.html.
    [2] https://www.cnblogs.com/laov/p/3434917.html.
    [3] https://mapr.com/blog/in-depth-look-hbase-architecture.
    [4] https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-bigdata-hbase/index.html.
    [5] https://www.edureka.co/blog/overview-of-hbase-storage-architecture.
    [6] https://www.toadworld.com/platforms/nosql/b/weblog/archive/2013/10/14/avoiding-hbase-reliability-problems.
    [7] http://www.benstopford.com/2009/11/24/understanding-the-shared-nothing-architecture.
    [8] Lee S. Shared-nothing vs. shared-disk cloud database architecture[J]. International Journal of Energy, Information and Communications, 2011, 2(4).

    展开全文
  • 区块链之分布式数据存储

    千次阅读 2018-08-23 17:14:26
    区块链之分布式数据存储 30年前,有一个未来学家提出未来世界的趋势是分布式将代替去中心化:一个机器蜘蛛的六条腿配置分布式的计算引擎,去掉中心化的大脑,结果是这个机器蜘蛛的六条腿之间能够协调自如。 现在的...
  • 分布式数据访问层(DAL)

    千次阅读 2017-02-11 00:46:21
    概述分布式(Distributed)数据访问层(Data Access Layer),简称DAL,是利用MySQL Proxy、Memcached、集群等技术优点而...分布式数据访问层是如何诞生的? 是由手机之家一位资深的开发者和架构师许超前最先提出的。(和
  • 分布式数据库的数据一致性管理是其最重要的内核技术之一,也是保证分布式数据库满足数据库最基本的ACID特性中的 “一致性”(Consistency)的保障。在分布式技术发展下,数据一致性的解决方法和技术也在不断的演进,...
  • Spark弹性分布式数据集RDD详解

    万次阅读 2016-12-03 13:01:06
    【Spark】弹性分布式数据集RDD概述弹性分布数据集RDDRDD(Resilient Distributed Dataset)是Spark的最基本抽象,是对分布式内存的抽象使用,实现了以操作本地集合的方式来操作分布式数据集的抽象实现。RDD是Spark最...
  • spring多数据源的配置(分布式事务管理
  • 分布式数据复制的三种方式

    千次阅读 2019-08-02 13:15:39
    现在主要讲下分布式数据复制。 将数据库分布到多台机器上,有多种原因: 可扩展性:数据量、读取负载、写入负载超过单台机器的处理能力。 容错/高可用:单台机器(或多台机器、网络或整个数据中心)出现故障的情况下...
  • Eventuate Platform是一个编写支持事务的微服务的事件机制平台,提供事件库服务,通过事件的订阅发布解决分布式数据管理的最终一致性。 1. Eventuate采用事件驱动的编程模型: 基于event sourcing的原子性操作 ...
  • 分布式管理

    千次阅读 2019-01-09 18:02:12
    分布式事物管理以及解决方案 1、什么是分布式事务 分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的...本质上来说,分布式事务就是为了保证不同数据库的数据一致性。...
  • 基于Lucene的搜索引擎服务器,分布式 Elasticsearch基础概念3-1 node 节点,部署Elasticsearch程序的服务器 cluster 集群,多个节点组成的架构 index 索引,相当于关系型数据库的database shar...
  •  JD_databus是为满足多数据中心项目的mysql在数据中心间复制的需求所产生的。最开始JD_databus是在LinkedIn的databus的基础上开发的,本次设计考虑到可维护性、代码的简洁、需求的快速迭代,决定重新开发。设计和...
  • 分布式配置管理平台Disconf

    千次阅读 2018-07-07 17:20:34
    disconf是一套完整的基于zookeeper的分布式配置统一解决方案功能特点:支持配置的分布式管理,配置发布统一化极简的使用方式(注解式编程 或 XML代码无代码侵入模式)需要Spring编程环境架构设计:每个模块的简单...
  • 事务 | Spring Cloud 分布式事务管理 LCN、GTX、ByteTCC

    万次阅读 多人点赞 2018-03-18 21:03:04
    事务 | Spring Cloud 分布式事务管理 LCN、GTX、ByteTCC 在微服务如火如荼的情况下,越来越多的项目开始尝试改造成微服务架构,微服务即带来了项目开发的方便性,又提高了运维难度以及网络不可靠的概率. Spring ...
  • BLUE DCS 分布式数据连接解决方案 1. 面临问题 随着计算机技术的飞速发展,应用系统的规模日趋庞大,结构和功能也日趋复杂,系统在集成过程中面临如下问题: 大型系统中数量众多的异构计算设备存在高性能数据通信的...
  • 弹性分布式数据集RDD概述

    千次阅读 2016-04-05 19:49:51
    RDD(Resilient Distributed Dataset)是Spark的最基本抽象,是对分布式内存的抽象使用,实现了以操作本地集合的方式来操作分布式数据集的抽象实现。RDD是Spark最核心的东西,它表示已被分区,不可变的并能够被并行...
  • 浅谈MongoDB数据库分布式存储管理

    千次阅读 2017-07-24 11:18:37
    分布式管理
  • 数据中心一体化协同分布式管理平台建设 发表时间:2013/1/28 林强 罗欢 来源:万方数据 关键字:广东电网云计算应用 云管理平台 数据中心一体化 信息化调查找茬投稿收藏评论好文推荐打印社区...
  • spring boot多数据分布式事务管理

    千次阅读 2018-08-28 18:59:47
    https://www.cnblogs.com/xiaofengfeng/p/9049363.html
  • 最近笔者在面试过程中发现,分布式的微服务开发越来越广泛了,越来越多的企业在面试时都需要有微服务的经验,那么在谈到微服务的过程中,很多的面试官都会问到一个问题:有没有接触过分布式事务管理?怎么实现分布式...
  • Spring Boot 分布式事物管理

    万次阅读 2018-01-28 22:33:54
    我的上一篇博文:Spring Boot 整合多数据源,里面讲解了Spring Boot整合多数据源,我们根据里面的例子来讲解Spring Boot多数据源的事务管理。 首先我们来改造之前我们的代码: 我们在User1Service中引入了数据源...
  • 什么是分布式数据存储

    千次阅读 2016-12-14 12:02:05
    传统的集中式存储对搭建和管理的要求较高。由于硬件设备的集中存放,机房的空间、散热和承重等都有严格的要求; 存储设备要求性能较好,对主干网络的带宽也有较高的要求。 而在信息爆炸的时代,人们可以获取的数据呈...
  • 分布式数据一致性(库存)

    千次阅读 2018-08-21 17:24:06
    库存冻结现状 目前购物车添加商品、删除商品、修改商品数量、购物车过期库存解冻、成单后清空购物车,都涉及库存变化。 以添加商品为例,目前实现逻辑...因购物车和库存系统分属不同的数据库,此处涉及分布式事务...
  • 小弟刚入IT行业,现要设计一个采集机(相当于一个服务器),用zookeeper、jafka进行分布式管理,采集系统域内设备性能(cpu、内存、流量控制等信息并实现拓扑发现功能包含二层三层设备),想问问大家设计的方法如何...
  • TDW开源:腾讯的分布式数据仓库

    千次阅读 2014-05-23 10:03:11
    腾讯分布式数据仓库 ( Tencent distributed Data Warehouse,简称TDW) 是腾讯基于开源软件研发的大数据处理平台,它基于Hadoop、Hive、PostgreSQL之上进行研发,历经4年多的研发和运营。目前,TDW已经开源。 腾讯...
  • 建设分布式双活数据中心是需要网络系统、存储系统、计算资源甚至包括应用系统等多个IT系统之间紧密合作才能实现的。用户所有的业务系统同时在两个数据中心运行,包括前端的全局负载均衡、服务器前端的负载均衡、...
  • 大数据的处理模式分为流处理和批处理两种。...因此,如果要求实时的处理大数据,必然要求采用分布式的方式,在这种情况下,除了应该考虑分布式系统的一致性问题,还将涉及到分布式系统网络时延的影响,这都增加...
  • 淘宝分布式配置管理服务Diamond

    万次阅读 2014-10-12 12:57:34
    在一个分布式环境中,同类型的服务...zookeeper的一种应用就是分布式配置管理(基于ZooKeeper的配置信息存储方案的设计与实现)。百度也有类似的实现:disconf。 Diamond则是淘宝开源的一种分布式配置管理服务的实现。D

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 519,815
精华内容 207,926
关键字:

分布式数据管理