SpringBoot第31讲:SpringBoot集成ShardingJDBC - Sharding-JDBC简介和基于MyBatis的单库分表

SpringBoot第31讲:SpringBoot集成ShardingJDBC - Sharding-JDBC简介和基于MyBatis的单库分表

本文是SpringBoot第31讲,主要介绍分表分库,以及SpringBoot集成基于ShardingJDBC+MyBatis的单库分表实践

文章目录

  • SpringBoot第31讲:SpringBoot集成ShardingJDBC - Sharding-JDBC简介和基于MyBatis的单库分表
    • 1、知识准备
      • 1.1、为什么要分表分库?
      • 1.2、什么是Sharding-JDBC?
      • 1.3、和ShardingSphere是什么关系?
    • 2、简单示例
      • 2.1、准备DB和依赖配置
      • 2.2、DAO
      • 2.3、Service
      • 2.4、Controller
      • 2.5、简单测试
    • 3、进一步理解
      • 3.1、几个常见的错误
      • 3.2、核心作者采访谈Sharding-JDBC
    • 4、示例源码

1、知识准备

主要理解分表分库,Sharding-JDBC要解决什么问题,Sharding-JDBC及ShardingSphere的关系等。

1.1、为什么要分表分库?

可以参考这篇文章:MySQL第七讲:MySQL分库分表详解

1.2、什么是Sharding-JDBC?

来自ShardingSphere官网

Sharding-JDBC是ShardingSphere的第一个产品,也是ShardingSphere的前身。 它定位为轻量级Java框架,在Java的JDBC层提供的额外服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

  • 适用于任何基于Java的ORM框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template或直接使用JDBC。
  • 基于任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, Druid, HikariCP等。
  • 支持任意实现JDBC规范的数据库。目前支持MySQL,Oracle,SQLServer 和 PostgreSQL。

img

1.3、和ShardingSphere是什么关系?

来自ShardingSphere官网

ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成。 他们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。

ShardingSphere定位为关系型数据库中间件,旨在充分合理地在分布式的场景下利用关系型数据库的计算和存储能力,而并非实现一个全新的关系型数据库。 它与NoSQL和NewSQL是并存而非互斥的关系。NoSQL和NewSQL作为新技术探索的前沿,放眼未来,拥抱变化,是非常值得推荐的。反之,也可以用另一种思路看待问题,放眼未来,关注不变的东西,进而抓住事物本质。 关系型数据库当今依然占有巨大市场,是各个公司核心业务的基石,未来也难于撼动,我们目前阶段更加关注在原有基础上的增量,而非颠覆

img

对应的版本功能

img

2、简单示例

这里主要介绍SpringBoot集成基于ShardingJDBC的单库分表实践,主要承接之前的相关文章在MyBatis的注解方式的基础上实现的。

2.1、准备DB和依赖配置

创建MySQL的schema db_user_sharding, 导入SQL 文件如下

DROP TABLE IF EXISTS `tb_role_0`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `tb_role_0` (
  `id` bigint NOT NULL,
  `name` varchar(255) NOT NULL,
  `role_key` varchar(255) NOT NULL,
  `description` varchar(255) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `tb_role_0`
--

LOCK TABLES `tb_role_0` WRITE;
/*!40000 ALTER TABLE `tb_role_0` DISABLE KEYS */;
INSERT INTO `tb_role_0` VALUES (3,'333','333','33','2021-09-08 17:09:15','2021-09-08 17:09:15');
/*!40000 ALTER TABLE `tb_role_0` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `tb_role_1`
--

DROP TABLE IF EXISTS `tb_role_1`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `tb_role_1` (
  `id` bigint NOT NULL,
  `name` varchar(255) NOT NULL,
  `role_key` varchar(255) NOT NULL,
  `description` varchar(255) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `tb_role_1`
--

LOCK TABLES `tb_role_1` WRITE;
/*!40000 ALTER TABLE `tb_role_1` DISABLE KEYS */;
INSERT INTO `tb_role_1` VALUES (1,'admin','admin','admin','2021-09-08 17:09:15','2021-09-08 17:09:15'),(2,'11','11','11','2021-09-08 17:09:15','2021-09-08 17:09:15');
/*!40000 ALTER TABLE `tb_role_1` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `tb_user_0`
--

DROP TABLE IF EXISTS `tb_user_0`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `tb_user_0` (
  `id` bigint NOT NULL,
  `user_name` varchar(45) NOT NULL,
  `password` varchar(45) NOT NULL,
  `email` varchar(45) DEFAULT NULL,
  `phone_number` int DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `tb_user_0`
--

LOCK TABLES `tb_user_0` WRITE;
/*!40000 ALTER TABLE `tb_user_0` DISABLE KEYS */;
INSERT INTO `tb_user_0` VALUES (718415228786159616,'qiwenjie','dad','1172814226@qq.com',121212121,'qwj','2022-04-06 20:45:38','2022-04-06 20:45:38');
/*!40000 ALTER TABLE `tb_user_0` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `tb_user_1`
--

DROP TABLE IF EXISTS `tb_user_1`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `tb_user_1` (
  `id` bigint NOT NULL,
  `user_name` varchar(45) NOT NULL,
  `password` varchar(45) NOT NULL,
  `email` varchar(45) DEFAULT NULL,
  `phone_number` int DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `tb_user_1`
--

LOCK TABLES `tb_user_1` WRITE;
/*!40000 ALTER TABLE `tb_user_1` DISABLE KEYS */;
INSERT INTO `tb_user_1` VALUES (1,'qwj1','dfasdf','15868860041@163.com',1212121213,'afsdfsaf','2021-09-08 17:09:15','2021-09-08 17:09:15'),(718415481409089537,'qwj2','dad2','13545670886@169.com',1212121212,'qwj2','2022-04-06 20:46:38','2022-04-06 20:46:38');
/*!40000 ALTER TABLE `tb_user_1` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `tb_user_role_0`
--

DROP TABLE IF EXISTS `tb_user_role_0`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `tb_user_role_0` (
  `id` bigint NOT NULL,
  `user_id` bigint NOT NULL,
  `role_id` bigint NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `tb_user_role_0`
--

LOCK TABLES `tb_user_role_0` WRITE;
/*!40000 ALTER TABLE `tb_user_role_0` DISABLE KEYS */;
INSERT INTO `tb_user_role_0` VALUES (1,1,1);
/*!40000 ALTER TABLE `tb_user_role_0` ENABLE KEYS */;
UNLOCK TABLES;

--
-- Table structure for table `tb_user_role_1`
--

DROP TABLE IF EXISTS `tb_user_role_1`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `tb_user_role_1` (
  `id` bigint NOT NULL,
  `user_id` bigint NOT NULL,
  `role_id` bigint NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `tb_user_role_1`
--

LOCK TABLES `tb_user_role_1` WRITE;
/*!40000 ALTER TABLE `tb_user_role_1` DISABLE KEYS */;
INSERT INTO `tb_user_role_1` VALUES (11,718415481409089537,3),(13,718415228786159616,2);
/*!40000 ALTER TABLE `tb_user_role_1` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2022-04-06 23:06:23

引入maven依赖, 包含mysql驱动,mybatis和pageHelper, 以及sharding-jdbc的依赖。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.1.0</version>
</dependency>
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.10</version>
</dependency>
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>sharding-jdbc-spring-boot-starter</artifactId>
    <version>4.1.1</version>
</dependency>

增加yml配置

spring:
  shardingsphere:
    datasource:
      names: ds
      ds:
        type: com.zaxxer.hikari.HikariDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        jdbc-url: jdbc:mysql://localhost:3306/db_user_sharding?allowPublicKeyRetrieval=true&useSSL=false&autoReconnect=true&characterEncoding=utf8
        username: root
        password: qwj930828
    sharding:
      tables:
        tb_user:
          actual-data-nodes: ds.tb_user_$->{0..1}
          table-strategy:
            inline:
              sharding-column: id
              algorithm-expression: tb_user_$->{id % 2}
          key-generator:
            column: id
            type: SNOWFLAKE
            props:
              worker:
                id: 123
      binding-tables: tb_user
      broadcast-tables: t_address
mybatis:
  type-aliases-package: springboot.shardingjdbc.mybatis.tables.entity
  configuration:
  	# 开启二级缓存
    cache-enabled: true
    use-generated-keys: true
    default-executor-type: REUSE
    use-actual-param-name: true

2.2、DAO

mapper/dao

package springboot.shardingjdbc.mybatis.tables.dao;

import org.apache.ibatis.annotations.*;
import springboot.shardingjdbc.mybatis.tables.dao.provider.UserDaoProvider;
import springboot.shardingjdbc.mybatis.tables.entity.User;
import springboot.shardingjdbc.mybatis.tables.entity.query.UserQueryBean;

import java.util.List;

/**
 * @author qiwenjie
 */
@Mapper
public interface IUserDao {

    String SELECT_USER_SQL = "select u.id, u.password, u.user_name, u.email, u.phone_number, u.description, u.create_time, u.update_time from tb_user u";

    @Results(
            id = "UserResult",
            value = {
                    @Result(property = "id", column = "id"),
                    @Result(property = "userName", column = "user_name"),
                    @Result(property = "password", column = "password"),
                    @Result(property = "email", column = "email"),
                    @Result(property = "phoneNumber", column = "phone_number"),
                    @Result(property = "description", column = "description"),
                    @Result(property = "createTime", column = "create_time"),
                    @Result(property = "updateTime", column = "update_time")
            }
    )
    @Select({SELECT_USER_SQL, " where id = #{id}"})
    User findById(@Param("id") Long id);

    @ResultMap("UserResult")
    @Select(SELECT_USER_SQL)
    User findAll();

    @ResultMap("UserResult")
    @Select({"<script> ", SELECT_USER_SQL, " where u.id != 0\n" +
            "\t\t<if test=\"userName != null and userName != ''\">\n" +
            "AND u.user_name like concat('%', #{user_name}, '%')\n" +
            "\t\t</if>\n" +
            "\t\t<if test=\"description != null and description != ''\">\n" +
            "AND u.description like concat('%', #{description}, '%')\n" +
            "\t\t</if>\n" +
            "\t\t<if test=\"phoneNumber != null and phoneNumber != ''\">\n" +
            "AND u.phone_number like concat('%', #{phoneNumber}, '%')\n" +
            "\t\t</if>\n" +
            "\t\t<if test=\"email != null and email != ''\">\n" +
            "AND u.email like concat('%', #{email}, '%')\n" +
            "\t\t</if>", " </script>"})
    List<User> findList(UserQueryBean userQueryBean);

    @Delete("delete from tb_user where id = #{id}")
    int deleteById(Long id);

    @Delete({"<script> ", "delete from tb_user where id in\n" +
            "<foreach collection=\"array\" item=\"id\" open=\"(\" separator=\",\" close=\")\">\n" +
            "#{id}\n" +
            "</foreach>", " </script>"})
    int deleteByIds(Long[] ids);

    @Update({"<script> ", "update tb_user\n" +
            " <set>\n" +
            " <if test=\"userName != null and userName != ''\">user_name = #{userName},</if>\n" +
            " <if test=\"email != null and email != ''\">email = #{email},</if>\n" +
            " <if test=\"phoneNumber != null and phoneNumber != ''\">phone_number = #{phoneNumber},</if>\n" +
            " <if test=\"description != null and description != ''\">description = #{description},</if>\n" +
            " update_time = sysdate()\n" +
            " </set>\n" +
            " where id = #{id}", " </script>"})
    int update(User user);

    @Insert({"<script> ", "insert into tb_user(\n" +
            " <if test=\"userName != null and userName != ''\">user_name,</if>\n" +
            " <if test=\"password != null and password != ''\">password,</if>\n" +
            " <if test=\"email != null and email != ''\">email,</if>\n" +
            " <if test=\"phoneNumber != null and phoneNumber != ''\">phone_number,</if>\n" +
            " <if test=\"description != null and description != ''\">description,</if>\n" +
            " create_time,\n" +
            " update_time\n" +
            " )values(\n" +
            " <if test=\"userName != null and userName != ''\">#{userName},</if>\n" +
            " <if test=\"password != null and password != ''\">#{password},</if>\n" +
            " <if test=\"email != null and email != ''\">#{email},</if>\n" +
            " <if test=\"phoneNumber != null and phoneNumber != ''\">#{phoneNumber},</if>\n" +
            " <if test=\"description != null and description != ''\">#{description},</if>\n" +
            " sysdate(),\n" +
            " sysdate()\n" +
            " )", " </script>"})
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int save(User user);

    @Update({"update tb_user set password = #{password}, update_time = sysdate()", " where id = #{id}"})
    int updatePassword(User user);

    @ResultMap("UserResult")
    @SelectProvider(type = UserDaoProvider.class, method = "findById")
    User findById2(Long id);
}

2.3、Service

user service 接口

package springboot.shardingjdbc.mybatis.tables.service;

import springboot.shardingjdbc.mybatis.tables.entity.User;
import springboot.shardingjdbc.mybatis.tables.entity.query.UserQueryBean;
import java.util.List;

/**
 * @author qiwenjie
 */
public interface IUserService {

    List<User> findList(UserQueryBean userQueryBean);

    User findById(Long id);

    int deleteById(Long id);

    int deleteByIds(Long[] ids);

    int update(User user);

    int save(User user);

    int updatePassword(User user);

    User findById2(Long userId);
}

service实现类

package springboot.shardingjdbc.mybatis.tables.service.impl;

import springboot.shardingjdbc.mybatis.tables.dao.IUserDao;
import springboot.shardingjdbc.mybatis.tables.entity.User;
import springboot.shardingjdbc.mybatis.tables.entity.query.UserQueryBean;
import org.springframework.stereotype.Service;
import springboot.shardingjdbc.mybatis.tables.service.IUserService;
import java.util.List;

@Service
public class UserDoServiceImpl implements IUserService {

    /**
     * userDao.
     */
    private final IUserDao userDao;

    /**
     * init.
     *
     * @param userDao2 user dao
     */
    public UserDoServiceImpl(final IUserDao userDao2) {
        this.userDao = userDao2;
    }

    @Override
    public List<User> findList(UserQueryBean userQueryBean) {
        return userDao.findList(userQueryBean);
    }

    @Override
    public User findById(Long id) {
        return userDao.findById(id);
    }

    @Override
    public int deleteById(Long id) {
        return userDao.deleteById(id);
    }

    @Override
    public int deleteByIds(Long[] ids) {
        return userDao.deleteByIds(ids);
    }

    @Override
    public int update(User user) {
        return userDao.update(user);
    }

    @Override
    public int save(User user) {
        return userDao.save(user);
    }

    @Override
    public int updatePassword(User user) {
        return userDao.updatePassword(user);
    }

    @Override
    public User findById2(Long userId) {
        return userDao.findById2(userId);
    }
}

2.4、Controller

user controller

package springboot.shardingjdbc.mybatis.tables.controller;


import springboot.shardingjdbc.mybatis.tables.entity.User;
import springboot.shardingjdbc.mybatis.tables.entity.query.UserQueryBean;
import springboot.shardingjdbc.mybatis.tables.entity.response.ResponseResult;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springboot.shardingjdbc.mybatis.tables.service.IUserService;
import java.util.List;

/**
 * @author qiwenjie
 */
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private IUserService userService;

    /**
     * @param user user param
     * @return user
     */
    @ApiOperation("Add/Edit User")
    @PostMapping("add")
    public ResponseResult<User> add(User user) {
        if (user.getId() == null) {
            userService.save(user);
        } else {
            userService.update(user);
        }
        return ResponseResult.success(userService.findById(user.getId()));
    }

    /**
     * @return user list
     */
    @ApiOperation("Query User One")
    @GetMapping("edit/{userId}")
    public ResponseResult<User> edit(@PathVariable("userId") Long userId) {
        return ResponseResult.success(userService.findById(userId));
    }

    /**
     * @return user list 2
     */
    @ApiOperation("Query User One 2")
    @GetMapping("edit2/{userId}")
    public ResponseResult<User> edit2(@PathVariable("userId") Long userId) {
        return ResponseResult.success(userService.findById2(userId));
    }

    /**
     * @return user list
     */
    @ApiOperation("Query User List")
    @GetMapping("list")
    public ResponseResult<List<User>> list(UserQueryBean userQueryBean) {
        return ResponseResult.success(userService.findList(userQueryBean));
    }

    @ApiOperation("Delete by id")
    @PostMapping("delete")
    public ResponseResult<Integer> delete(Long userId) {
        return ResponseResult.success(userService.deleteById(userId));
    }
}

2.5、简单测试

访问页面:

http://localhost:8080/doc.html

插入数据
在这里插入图片描述

查询数据
在这里插入图片描述

3、进一步理解

通过几个问题进一步理解。

3.1、几个常见的错误

在使用sharding-jdbc以及和其它组件集成(比如mybatis,mybatis-plus,druid等)遇到的问题会比较多,这里举几个典型的报错例子:

  • 问题1、Sharding value must implements Comparable.

由于数据分片,原有的数据库自动增长ID设置以及ORM层相关配置策略都不能再使用,所以需要取消数据库自增长以及ORM层@ID或者@TableID等注解

key-generator 由如下配置替代

  key-generator:
    column: id
    type: SNOWFLAKE
    props:
      worker:
        id: 123
  • 问题2、Data truncation: Out of range value for column ‘id’

正是由于上述SNOWFLAKE雪花算法(相关文章请参考数据结构与算法第二十讲:分布式算法之Snowflake算法), 相关ID是64位的long类型,所以需要设置相关字段位BIGINT类型。

  • 问题3、java.sql.SQLFeatureNotSupportedException: getObject with type

这是与Mybatis等其它框架集成的一个bug:LocalDateTimeTypeHandler未能进行关联处理; 官方在5.0版本修复了这个问题,只是当前sharding-jdbc-spring-boot-starter 的版本依然是4.1.1,所以依然有问题。这也凸显出了国产开源(即便是进入Apache且在不断完善)整体上还有很长的路(文档,闭环,Ecosystem…等等)要走。https://github.com/apache/shardingsphere/pull/6202

3.2、核心作者采访谈Sharding-JDBC

深度认识 Sharding-JDBC:做最轻量级的数据库中间层

4、示例源码

todo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/61436.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

continue有什么作用

学习算法以来&#xff0c;break使用的比较多&#xff0c;continue使用的比较少&#xff0c;只知道break是跳出循环的作用,不知道continue有什么作用。 continue可以跳过本次循环&#xff0c;强制执行下一次循环。 比如这个代码 #include<iostream>using namespace std…

Swish - Mac 触控板手势窗口管理工具[macOS]

Swish for Mac是一款Mac触控板增强工具&#xff0c;借助直观的两指轻扫&#xff0c;捏合&#xff0c;轻击和按住手势&#xff0c;就可以从触控板上控制窗口和应用程序。 Swish for Mac又不仅仅只是一个窗口管理器&#xff0c;Swish具有28个易于使用的标题栏&#xff0c;停靠栏…

element+vue 之动态form

1.页面部分 <div v-for"(item,index) in formList" :key"index"><el-col :span"6" v-if"item.inputType0"><el-form-item :label"item.conditionName" :prop"item.conditionCode":rules"{req…

网络安全(黑客)自学就业

前段时间&#xff0c;遇到网友提问&#xff0c;说为什么我信息安全专业的找不到工作&#xff1f; 造成这个结果主要是有两大方面的原因。 第一个原因&#xff0c;求职者本身的学习背景问题。那这些问题就包括学历、学校学到的知识是否扎实&#xff0c;是否具备较强的攻防实战…

【C++】——模板

目录 泛型编程函数模板函数模板的概念函数模板格式&#xff1a;函数模板的原理函数模板的实例化模板参数的匹配原则 类模板类模板定义格式类模板的实例化 泛型编程 泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础 引例…

Go For Web:Golang http 包详解(源码剖析)

正文&#xff1a; Golang http 包详解&#xff08;源码剖析&#xff09; 前面小节我们认识了 Web 的工作方式&#xff0c;也成功用 Go 搭建了一个最简单的 Web 服务了解了 Golang 运行 Web 的原理。现在我们详细地去解剖以下 http 包&#xff0c;看看它如何实现整个过程的 Go…

【UEC++学习】UE网络 - Replication、RPC

1. UE网络架构 &#xff08;1&#xff09;UE的网络架构是SC&#xff08;Server - Client&#xff09;的模式&#xff0c;这种模式的优势&#xff1a;这种模式让所有客户端都在服务器端进行安全验证&#xff0c;这样可以有效的防止客户端上的作弊问题。 &#xff08;2&#xff…

机器学习和深度学习简述

一、人工智能、机器学习、深度学习的关系 近些年人工智能、机器学习和深度学习的概念十分火热&#xff0c;但很多从业者却很难说清它们之间的关系&#xff0c;外行人更是雾里看花。概括来说&#xff0c;人工智能、机器学习和深度学习覆盖的技术范畴是逐层递减的&#xff0c;三…

Linux命令200例:grep强大的文本搜索工具使用及15个精选示例(常用)

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;阿里云社区专家博主&#xff0c;2023年6月csdn上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f3c6;本文已…

[C++] 类与对象(中)完整讲述运算符重载示例 -- 日期类(Date) -- const成员

目录 1、前言 2、全缺省的构造函数 3、打印接口 4、拷贝构造 5、赋值运算符重载&#xff08;operator&#xff09; 5.1赋值重载是默认成员函数&#xff0c;重载格式&#xff1a; 5.2 赋值重载不能为全局函数 5.3 编译器默认生成 6、析构函数 7、operator> 8、ope…

国内GitHub加速访问工具-Fetch GitHub Hosts

一、工具介绍 Fetch GitHub Hosts是一款开源跨平台的国内GitHub加速访问工具&#xff0c;主要为解决研究及学习人员访问 Github 过慢或其他问题而提供的 Github Hosts 同步工具。 项目原理&#xff1a;是通过部署此项目本身的服务器来获取 github.com 的 hosts&#xff0c;而…

MySql之索引下推

什么是索引下推 索引下推(Index Condition Pushdown&#xff0c;简称ICP)&#xff0c;是MySQL5.6版本的新特性&#xff0c;它能减少回表查询次数&#xff0c;提高查询效率。 索引下推优化的原理 我们先简单了解一下MySQL大概的架构&#xff1a; MySQL服务层负责SQL语法解析、…

图解java.util.concurrent并发包源码系列——深入理解AQS,看完可以吊打面试官

图解java.util.concurrent并发包源码系列——深入理解AQS&#xff0c;看完可以吊打面试官 AQS是什么&#xff1f;有什么作用&#xff1f;AQS的原理自定义资源资源的获取与释放线程阻塞等待唤醒 AQS源码核心成员变量Node 的内部结构waitStatusprev、next、threadnextWaiterprede…

网络安全公司校招面试会面试那些问题?

面试官会从那些方面去考察面试者&#xff1f; 以某安全公司的技术支持工程师岗位为例 面试官可能会从网络技术、操作系统、数据库、项目经验、语言表达以及个人擅长技能方面展开 面试官会提出那些问题来考查面试者呢&#xff1f; 网络基础方面的问题&#xff1a;请介绍一下…

运输层---概述

目录 运输层主要内容一.概述和传输层服务1.1 概述1.2 传输服务和协议1.3 传输层 vs. 网络层1.4 Internet传输层协议 二. 多路复用与多路分解&#xff08;解复用&#xff09;2.1 概述2.2 无连接与面向连接的多路分解&#xff08;解复用&#xff09;2.3面向连接的多路复用*2.4 We…

《Python入门到精通》函数详解

「作者主页」&#xff1a;士别三日wyx 「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;小白零基础《Python入门到精通》 函数 1、函数的调用2、函数的参数2.1、变量的就近原则2.2、传递参数2.3、形参和实…

wonderful-sql 作业

Sql 作业 作业1&#xff1a; 答&#xff1a; create table Employee (Id integer not null, Name varchar(32) , Salary integer, departmentId integer, primary key (Id) );create table Department( Id integer primary key, Name varchar(30) not null );insert into emp…

Python学习笔记:List、Tuple、for循环

1.list list_demo [7, 7, 8, 9, 9, 9] print(list_demo.index(7)) # index 方法返回第一个index list_demo.sort() # 排序list list_demo.reverse() # 倒序list list_demo1 list_demo.copy() # 复制list 2.matrix 其实就是list嵌套&…

网络开发-IO模型

基本概念 I/O即数据的读取&#xff08;接收&#xff09;或写入&#xff08;发送&#xff09;操作 通常用户进程中的一个完整I/O分为两个阶段 用户进程空间<-->内核空间内核空间<-->设备空间&#xff08;磁盘、网卡等&#xff09; I/O分为内存I/O、网络I/O和磁盘…

宝塔Linux面板升级“获取更新包失败”怎么解决?

宝塔Linux面板执行升级命令后失败&#xff0c;提示“获取更新包失败&#xff0c;请稍后更新或联系宝塔运维”如何解决&#xff1f;新手站长分享宝塔面板升级失败的解决方法&#xff1a; 宝塔面板升级失败解决方法 1、使用root账户登录到你的云服务器上&#xff0c;宝塔Linux面…