springboot整合ShardingSphere5-0-0-alpha实现读写分离示例

续上篇springboot整合ShardingSphere5-0-0-alpha实现分库分表示例,
在上篇的基础上,略作修改则可实现读写分离配置。

关于读写分离

在平时项目中,我觉得更加常用的是分库分表数据分片,读写分离比较少用到,对于某些特殊场景,还是有一定意义,比如,对于订单或日志这种只增不减,流量较大时,写入场景对数据库的压力会影响到读取速度,就比较适合做读写分离,主从配置,一主多从,主库负责写入和修改删除等操作,从库只负责读取,从而写入数据库不会影响读取的性能,这里要保证主从数据库同步。主从配置是异步更新数据到从库的,所以写入之后肯定没那么快立马在从库看到,会有时间差,所以对于某些即时性要求高的场景,写入主库后,要么还是读主库,要么加redis缓存。
但是不一定非要用读写分离,读写分离的意义是缓解数据库的压力和访问速度,但是也带来了主从数据库同步,数据一致性等问题,缓解数据库压力的方法有很多,比如利用mysql+redis+elasticsearch等也可以达到同样甚至更好的效果,对于多数场景应该优先考虑使用缓存和搜索引擎,有点跑题了下面还是示例读写分离。

ShardingSphere5-0-0-alpha读写分离配置

ShardingSphere5-0-0-alpha提供的读写分离配置比数据库分片配置要简单的多,只要指定主从数据库,指定读库负载均衡算法(ReplicaLoadBalanceAlgorithm)配置就可以了,支持ROUND_ROBIN:轮询算法 RANDOM:随机访问算法两种负载均衡算法。
需要说明的是ShardingSphere5-0-0-alpha只是提供访问数据库的配置,不会做主从数据库数据同步的操作,数据同步可以在数据库里设置,这里先不考虑。
ShardingSphere5-0-0-alpha官方文档里有介绍:
“同一线程且同一数据库连接内,如有写入操作,以后的读操作均从主库读取,用于保证数据一致性”,所以ShardingSphere还是做了不少事。
在上篇的基础上只需要修改如下数据源配置:

    @Bean
    public DataSource dataSource() {
        // 配置真实数据源
        Map<String, DataSource> dataSourceMap = new HashMap<>();

        // 配置第 1 个数据源
        DruidDataSource dataSource1 = new DruidDataSource();
        dataSource1.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource1.setUrl("jdbc:mysql://127.0.0.1:3306/zhaohy?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=UTC");
        dataSource1.setUsername("root");
        dataSource1.setPassword("root");
        dataSourceMap.put("master", dataSource1);

        // 配置第 2 个数据源
        DruidDataSource dataSource2 = new DruidDataSource();
        dataSource2.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource2.setUrl("jdbc:mysql://127.0.0.1:3306/zhaohy1?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&serverTimezone=UTC");
        dataSource2.setUsername("root");
        dataSource2.setPassword("root");
        dataSourceMap.put("slave0", dataSource2);

        List<String> slaveList = new ArrayList<String>();
        slaveList.add("slave0");
        
         //配置读写分离规则
        List<ReplicaQueryDataSourceRuleConfiguration> configurations = new ArrayList<>();
        configurations.add(new ReplicaQueryDataSourceRuleConfiguration("ds", "master", slaveList, "load_balancer"));
        Map<String, ShardingSphereAlgorithmConfiguration> loadBalancers = new HashMap<>();
        //ROUND_ROBIN:轮询算法 RANDOM:随机访问算法
        loadBalancers.put("load_balancer", new ShardingSphereAlgorithmConfiguration("ROUND_ROBIN", new Properties()));
        ReplicaQueryRuleConfiguration ruleConfiguration = new ReplicaQueryRuleConfiguration(configurations, loadBalancers);
        List<RuleConfiguration> ruleConfigurationList = new ArrayList<RuleConfiguration>();
        ruleConfigurationList.add(ruleConfiguration);
        
        DataSource dataSource = null;
        try {
            dataSource = ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, ruleConfigurationList, new Properties());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        logger.info("datasource : {}", dataSource);
        return dataSource;
    }

上面代码中,指定两个数据库,主库master(zhaohy库)和从库slave0(zhaohy1库)(master和slave0名称可以自定义),从库还可以加多个,负载均衡算法指定的是ROUND_ROBIN:轮询算法,配置好之后下面在两个库都存在的t_test_0表里分别插入一条数据:
zhaohy库t_test_0:

insert into t_test_0 (title,author,date,title_id,column_id) values('Replica读写分离测试','zhaohy',now(),4,4);

zhaohy1库t_test_0:

insert into t_test_0 (title,author,date,title_id,column_id) values('Replica读写分离测试','zhaohySlave',now(),4,4);

把t_test_0的表结构贴一下:

CREATE TABLE `t_test_0` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(100) NOT NULL,
  `author` varchar(40) NOT NULL,
  `date` datetime DEFAULT NULL,
  `title_id` varchar(32) DEFAULT NULL,
  `column_id` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8

可以看到主库author字段插入的是'zhaohy',从库author字段插入的是'zhaohySlave',下面写测试接口,一个读取接口,一个插入接口,一个修改接口,一个删除接口,如果查t_test_0表查出来是zhaohySlave,说明读取用的是从库,如果插入之后在主库可以查询到说明插入用的是主库,如果更改之后在主库能看到更改成功说明更改的是主库,如果删除在主库也生效了说明用的也是主库,那就成功了。

测试

controller:

    @RequestMapping("/test/replicaSelect.do")
    public void replicaSelect(HttpServletRequest request) {
        testService.replicaSelect();
    }
    @RequestMapping("/test/insertReplicaSelect.do")
    public void insertReplicaSelect(HttpServletRequest request) {
        testService.insertReplicaSelect();
    }
    @RequestMapping("/test/updateReplicaSelect.do")
    public void updateReplicaSelect(HttpServletRequest request) {
        testService.updateReplicaSelect();
    }
    @RequestMapping("/test/deleteReplicaSelect.do")
    public void deleteReplicaSelect(HttpServletRequest request) {
        testService.deleteReplicaSelect();
    }

serviceImpl:

    @Override
    public void replicaSelect() {
        List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
        Map<String, Object> paramsMap = new HashMap<String, Object>();
        list = testMapper.replicaSelect(paramsMap);
        System.out.println("===" + JSON.toJSONString(list));
        
    }
    @Override
    public void insertReplicaSelect() {
        Map<String, Object> paramsMap = new HashMap<String, Object>();
        //paramsMap.put("id", "2");
        paramsMap.put("columnId", 6);
        paramsMap.put("title", "Replica读写分离测试写入");
        paramsMap.put("author", "zhaohyMaster");
        paramsMap.put("titleId", 6);
        testMapper.insertReplicaSelect(paramsMap);
        System.out.println("插入完成!");
    }


    @Override
    public void updateReplicaSelect() {
        Map<String, Object> paramsMap = new HashMap<String, Object>();
        paramsMap.put("title", "Replica读写分离测试修改");
        paramsMap.put("author", "zhaohyMaster");
        testMapper.updateReplicaSelect(paramsMap);
        System.out.println("修改完成!");
    }


    @Override
    public void deleteReplicaSelect() {
        Map<String, Object> paramsMap = new HashMap<String, Object>();
        paramsMap.put("author", "zhaohyMaster");
        testMapper.deleteReplicaSelect(paramsMap);
        System.out.println("删除完成!");
    }

mapper:

List<Map<String, Object>> replicaSelect(Map<String, Object> paramsMap);
void insertReplicaSelect(Map<String, Object> paramsMap);

void updateReplicaSelect(Map<String, Object> paramsMap);

void deleteReplicaSelect(Map<String, Object> paramsMap);

xml:

<select id="replicaSelect" resultType="java.util.HashMap">
        select * from t_test_0
</select>
<insert id="insertReplicaSelect">
        insert into t_test_0 (title,author,date,title_id,column_id)values(#{title},#{author},now(),#{titleId},#{columnId})
</insert>
    
<update id="updateReplicaSelect">
    update t_test_0 set title = #{title} where author = #{author}
</update>
    
<delete id="deleteReplicaSelect">
    delete from t_test_0 where author = #{author}
</delete>

启动项目请求查询接口,控制台打印出来的json如下:

===[{"date":1610134448000,"column_id":"4","author":"zhaohySlave","title_id":"4","id":6,"title":"Replica读写分离测试"}]

查询出来的author是zhaohySlave,说明查的是从库,插入之后在主库能查到,说明插入的是主库,更改之后也是主库生效了,删除也在主库生效了,读写分离成功。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容