自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(57)
  • 收藏
  • 关注

原创 分布式事务

极速解决企业级分布式事务之spingCloud+tx-lcnhttps://blog.csdn.net/qq_33449307/article/details/102550878中我们实现了[springBoot+jpa+jta+atomikos实现分布式事务,模拟多数据源],这种方式基于2PC的,了解2PC,3PC会知道这些方式存在一些问题:1.引入了中间件中心化协调者 操作复杂化 一...

2019-11-30 20:44:23 79

原创 springBoot+jpa+jta+atomikos十分钟实现分布式事务,模拟多数据源

基于jta+atomikos解决分布式事务 模拟多数据源jta: Java Transactio API,即是java中对事务处理的api,api即是接口的意思.atomikos:Atomikos TransactionsEssentials 是一个为Java平台提供增值服务的并且开源类事务管理器,基于2PC协议.不明白XA 2PC 3PC TCC的同学可以花几分钟的时间去看一下.1....

2019-10-14 16:16:48 1934 1

原创 超哥教你10分钟搞定QueryDSL+JPA简化数据层操作

本博客在SpringBoot,maven,Mysql的环境下进行配置编写。一、环境配置1.引入maven依赖以及插件,以下是本demo的依赖(绿色字体部分是需要注意添加的依赖以及插件):插件:这里说明一下 添加的apt-maven-plugin 插件是为了让程序自动生成query type(查询实体,命名方式为:"Q"+对应实体名)上面引入的querydsl-...

2018-07-30 15:38:16 7332 12

原创 几种志框架:Log4j Log4j2 SLF4J logback和Apache Commons Logging的比较

作为Java开发人员,对于日志记录框架一定非常熟悉。而且几乎在所有应用里面,一定会用到各种各样的日志框架用来记录程序的运行信息。而对于一个成熟的Java应用,这个是必不可少的。在开发和调试阶段,日志可以帮助我们更快的定位问题;而在应用的运维过程中,日志系统又可以帮助我们记录大部分的异常信息,通常很多企业会通过收集日志信息来对系统的运行状态进行实时监控预警。总体概览image.png目前的日志框架有JDK自带的logging,log4j1、log4j2、logback ,这些框架都自己定制了.

2021-06-20 19:12:37 28

原创 四种JSON类库的性能比较---Gson、FastJson、Jackson、Json-lib

本篇通过JMH来测试一下Java中几种常见的JSON解析库的性能。每次都在网上看到别人说什么某某库性能是如何如何的好,碾压其他的库。但是百闻不如一见,只有自己亲手测试过的才是最值得相信的。JSON不管是在Web开发还是服务器开发中是相当常见的数据传输格式,一般情况我们对于JSON解析构造的性能并不需要过于关心,除非是在性能要求比较高的系统。目前对于Java开源的JSON类库有很多种,下面我们取4个常用的JSON库进行性能测试对比, 同时根据测试结果分析如果根据实际应用场景选择最合适的JSON库。这4个

2021-06-16 21:30:18 12

原创 5分钟学会SpringBoot整合nacos做注册中心和配置中心

1.运行服务端nacos官网地址1.下载nacos-server2.解压下载的文件,并进入解压后的nacos-data目录,删除derby-data目录。3.进入nacos/bin 执行命令: sh startup.sh -m standalone3.查看最后打印出来的start.out文件4.访问控制台服务端启动完毕2.nacos做配置中心 和 注册中心2.1 引入maven依赖 <!-- 配置中心的依赖 --> <dependency>

2021-06-15 22:32:43 4

原创 分布式中几种服务注册与发现组件的原理与比较

前言在云计算和容器化技术发展火热的当下,对于微服务架构,服务注册与发现组件是必不可少的。在传统的服务架构中,服务的规模处于运维人员的可控范围内。当部署服务的多个节点时,一般使用静态配置的方式实现服务信息的设定。在微服务应用中,服务实例的数量和网络地址都是动态变化的,这对系统运维提出了巨大的挑战。因此,动态的服务注册与发现就显得尤为重要。解决的问题在一个分布式系统中,服务注册与发现组件主要解决两个问题:服务注册和服务发现。服务注册:服务实例将自身服务信息注册到注册中心。这部分服务信息包括服务所在主机I

2021-06-09 19:54:44 11

原创 springBoot整合thrift

前言: thrift的基础知识1.Thrift的服务端1.1.引入maven依赖 <parent> <artifactId>com.ajc.demo</artifactId> <groupId>org.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <depende

2021-06-06 21:34:33 20 3

原创 小作文01-承蒙相爱

途经四季,总有一些遇见,因缘而起;总有一些心动,因爱而生。一些牵念,可跨千山万水,温暖的感觉溢满心间;几许清欢,亦是心满意足。时光流淌,幸福一直在身旁,从未遥远。

2021-06-06 19:44:39 61 2

原创 thrift+springBoot

1 基本语法1.1 数据类型基本类型:bool 布尔类型,true或者falsebyte 字节类型,长度为8位,有符号i16 16位有符号整形,java中的shorti32 32位有符号整形,java中的inti64 64位有符号整形,java中的longdouble 64位浮点数string 一串编码未知的文本或二进制串 需要注意的是,没有无符号整形。这是兼容多种语言所要求的(utf-8编码的字符串)。特殊类型:binary:未经过编码的字节流,java中的ByteBuffer。容

2021-06-02 20:23:55 6

原创 redis实现热搜榜

核心需求一个项目中,遇到了搜索热词统计的需求,我使用了 Redis 的五大数据类型之一 Sorted Set 实现。目前有两项数据需要统计:“当日搜索热词 top10”和“当周搜索热词 top10”。关于这两项数据的统计方法,目前想到了两种实现方法:两个 Redis 的 Sorted Set 实现,一个 Sorted Set A 统计当天,0 点 top10 记录进 MySQL,Sorted Set 清零。一个 Sorted Set B 统计当周,每周日 top10 记录进 MySQL,Sorted

2021-05-30 12:43:16 22

原创 static{}静态代码块与{}普通代码块之间的区别

先看一个例子://class A package com.my.test;class A { static { System.out.println("A1:父类静态代码区域"); } { System.out.println("A2:父类非静态代码区域"); } public A() { System.out.println("A3:父类构造器"); }}//class

2021-05-26 21:48:41 4

原创 熔断限流----Sentinel

1.功能特点丰富的应用场景:例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500台以下规模的集群的汇总运行情况。广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。完善

2021-05-23 22:43:10 37 2

原创 redis的数据结构zset---跳跃表

跳跃表是一种有序的数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。这么说,我们可能很难理解,我们可以先回忆一下链表。一、复习跳跃表1.1 什么是跳跃表对于一个单链表来讲,即便链表中存储的数据是有序的,如果我们要想在其中查找某个数据,也只能从头到尾遍历链表。这样查找效率就会很低,时间复杂度会很高,是 O(n)。如果我们想要提高其查找效率,可以考虑在链表上建索引的方式。每两个结点提取一个结点到上一级,我们把抽出来的那一级叫作索引。这个时候,我们假设要查找节点8,

2021-05-19 21:56:05 24

原创 一文搞懂XXL-JOB任务调度平台

一、概述在平时的业务场景中,经常有一些场景需要使用定时任务,比如:时间驱动的场景:某个时间点发送优惠券,发送短信等等。批量处理数据:批量统计上个月的账单,统计上个月销售数据等等。固定频率的场景:每隔5分钟需要执行一次。所以定时任务在平时开发中并不少见,而且对于现在快速消费的时代,每天都需要发送各种推送,消息都需要依赖定时任务去完成,应用非常广泛。二、为什么需要任务调度平台在Java中,传统的定时任务实现方案,比如Timer,Quartz等都或多或少存在一些问题:不支持集群、不支持统计、

2021-05-16 13:04:45 90 2

原创 Elasticsearch面试题

1. 什么是Elasticsearch?Elasticsearch 是一个基于 Lucene 的搜索引擎。它提供了具有 HTTP Web 界面和无架构 JSON 文档的分布式,多租户能力的全文搜索引擎。Elasticsearch 是用 Java 开发的,根据 Apache 许可条款作为开源发布。2. ES中的倒排索引是什么?传统的检索方式是通过文章,逐个遍历找到对应关键词的位置。倒排索引,是通过分词策略,形成了词和文章的映射关系表,也称倒排表,这种词典 + 映射表即为倒排索引。其中词典中存储词元

2021-05-12 22:07:48 157 9

原创 分布式事务几种解决方案

分布式事务分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。以上是百度百科的解释,简单的说,就是一次大的操作由不同的小操作组成,这些小的操作分布在不同的服务器上,且属于不同的应用,分布式事务需要保证这些小操作要么全部成功,要么全部失败。本质上来说,分布式事务就是为了保证不同数据库的数据一致性。以商品流水账单为例,我们拆分为商品购买系统,订单系统,支付系统。用户看中一件商品,点击购买。商品购买系统响应用户的点击,向订单系统插入一条订单信息。

2021-05-09 20:27:41 31 5

转载 关于序列化和反序列化

前言序列化:将java对象转化为可传输的字节数组反序列化:将字节数组还原为java对象为啥子要序列化?序列化最终的目的是为了对象可以跨平台存储,和进行网络传输。而我们进行跨平台存储和网络传输的方式就是IO,而我们的IO支持的数据格式就是字节数组什么情况下需要序列化?凡是需要进行跨平台存储和网络传输的数据,都需要进行序列化本质上存储和网络传输 都需要经过 把一个对象状态保存成一种跨平台识别的字节格式,然后其他的平台才可以通过字节信息解析还原对象信息序列化的方式序列化只是一种拆装组装对象的规则

2021-05-06 00:00:20 8 1

原创 Springboot启动扩展点超详细总结,再也不怕面试官问了

1.背景Spring的核心思想就是容器,当容器refresh的时候,外部看上去风平浪静,其实内部则是一片惊涛骇浪,汪洋一片。Springboot更是封装了Spring,遵循约定大于配置,加上自动装配的机制。很多时候我们只要引用了一个依赖,几乎是零配置就能完成一个功能的装配。我非常喜欢这种自动装配的机制,所以在自己开发中间件和公共依赖工具的时候也会用到这个特性。让使用者以最小的代价接入。想要把自动装配玩的转,就必须要了解spring对于bean的构造生命周期以及各个扩展接口。当然了解了bean的各个生命周

2021-05-02 23:47:05 47 1

原创 过滤器 (Filter) 和 拦截器 (Interceptor)

1.过滤器 (Filter)过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接口中定义了三个方法。init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。注意:这个方法必须执行成功,否则过滤器会不起作用。doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。destroy(): 当容器销毁 过滤器实例时调用

2021-04-28 23:28:48 3301 12

原创 Redis(一)------内存淘汰策略

前言作为一个内存数据库,redis在内存空间不足的时候,为了保证命中率,就会选择一定的数据淘汰策略。1.参数设置我们的redis数据库的最大缓存、主键失效、淘汰机制等参数都是通过配置文件来配置的。这个文件是我们的redis.config文件,我们的redis装在了/usr/local/redis目录下,所以配置文件也在这里。首先说明一下我使用的redis是5.0。1.1 最大内存参数关键的配置就在最下面,我们可以设置多少个字节。默认是关闭的。1.2 内存淘汰策略不同于之前的版本,redis5

2021-04-25 21:51:19 35

原创 mysql---主从复制

1.MySQL主从复制介绍MySQL数据库支持单向、双向、链式级联、环状等不同业务场景的复制。在复制过程中,一台服务器充当主服务器(Master),接收来自用户的内容更新,而一个或多个其他的服务器充当从服务器(Slave),接收来自主服务器binlog文件的日志内容,解析出SQL,重新更新到从数据库,使得主从服务器的数据达到一致。如果设置了链式级联复制,那么从服务器本身除了充当从服务器外,也会同时充当其下面从服务器的主服务器,链式级联复制类似A—>B—>C的复制形式。在这里,只介绍主—&gt

2021-04-25 21:34:59 43

原创 MySQL的Redo日志与Undo日志

1.重做日志(redo log)我们都知道,事务的四大特性里面有一个是 持久性 ,具体来说就是只要事务提交成功,那么对数据库做的修改就被永久保存下来了,不可能因为任何原因再回到原来的状态。那么 MySQL 是如何保证一致性的呢?最简单的做法是在每次事务提交的时候,将该事务涉及修改的数据页全部刷新到磁盘中。但是这么做会有严重的性能问题,主要体现在两个方面:因为 Innodb 是以页为单位进行磁盘交互的,而一个事务很可能只修改一个数据页里面的几个字节,这个时候将完整的数据页刷到磁盘的话,太浪费资源了。一

2021-04-21 22:22:58 20

原创 MySQL 是如何解决幻读的

1.什么是幻读在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读。而多或者少的那一行被叫做 幻行。就像出现了幻觉一样 所以叫幻读。2.为什么要解决幻读在高并发数据库系统中,需要保证事务与事务之间的隔离性,还有事务本身的一致性。3.MySQL 是如何解决幻读的3.1 多版本并发控制(MVCC)(快照读/一致性读)多数数据库都实现了多版本并发控制,并且都是靠保存数据快照来实现的。以 InnoDB 为例。可以理解为每一行中都冗余了两个字段,一个是行的创建版本,一个是行的删除(过期)版本

2021-04-21 21:51:42 24

原创 设计模式---单例模式

单例模式定义: 单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自行创建这个实例的一种模式。特点:单例类只有一个实例对象;该单例对象必须由单例类自行创建;单例类对外提供一个访问该单例的全局访问点。优点单例模式可以保证内存里只有一个实例,减少了内存的开销。可以避免对资源的多重占用。单例模式设置全局访问点,可以优化和共享资源的访问。缺点单例模式一般没有接口,扩展困难。如果要扩展,则除了修改原来的代码,没有第二种途径,违背开闭原则。在并发测试中,单例模式不利于

2021-04-20 21:10:20 12

翻译 一文明白设计模式的6大原则和23种设计模式

1.单一职责原则思想:一个方法只负责一件事情。描述:单一职责原则很简单,一个方法 一个类只负责一个职责,各个职责的程序改动,不影响其它程序。 这是常识,几乎所有程序员都会遵循这个原则。优点:降低类和类的耦合,提高可读性,增加可维护性和可拓展性,降低可变性的风险。2.里氏替换原则思想:使用的基类可以在任何地方使用继承的子类,完美的替换基类。描述:子类可以扩展父类的功能,但不能改变父类原有的功能。子类可以实现父类的抽象方法,但不能覆盖父类的非抽象方法,子类中可以增加自己特有的方法。优点:增.

2021-04-20 20:32:45 17

原创 Spring中的设计模式

1.简单工厂或叫做静态工厂方法(StaticFactory Mehtod)模式,但不属于23种GOF设计模式之一。简单工厂的实质是由一个工厂类根据传入的参数,动态决定创建哪一个产品类。Spring中的BeanFactory就是简单工厂的体现,根据传入一个唯一的标识来获得bean对象,但是否在传入参数后创建还是传入参数前创建要根据具体情况来定。2.工厂方法(Factory Method)通常由应用程序直接使用new创建新的对象,为了将对象的创建和使用相分离,采用工厂模式,即应用程序将对象的创建及初始

2021-04-20 20:17:22 8

原创 word的使用(一)---表格操作

1.插入表格1.1 插入–表格–选择word中插入表格一般都是通过工具栏插入—表格来实现点击表格的最后一行的最后一格,按下TAB键,可以增加一行1.2 通过类命令插入表格通过输入“±----±----+”和回车键来快速插入表格,“±----+“按回车插入1行1列,“±----±----+”插入1行2列,以此类推,中间的”-----"减号代表表格的宽度,减号越长表格越宽。插入一行后按Tab可以增加行。2.表格样式2.1 表格设计选中菜单栏的表格设计,可以选择表格的基本样式2.2 表格

2021-04-18 23:19:37 45

原创 Mybatis-Plus最优雅的使用

1.代码生成开源的代码生成器有很多,我这里使用 人人开源的 renren-generator下载之后可根据需要修改里面的模板文件。①修改application.yml中的DB配置②run 起工程③访问 127.0.0.1:80 打开控制台,选择renren-fast 勾选要生成代码的数据表。生成一个renren.zip的包 解压 把对应的文件copy到我们工程的对应位置既可。这里分页插件可能要修改一下,可以根据自己喜欢的方式选择一个mybatis的分页插件。2.优雅的使用在操作单表的时

2021-04-14 20:49:08 46

原创 限流(一)---限流的几种方案

1.限流方案限流的实现方案有很多种,这里稍微理了一下,限流的分类如下所示:①合法性验证限流:比如验证码、IP 黑名单等,这些手段可以有效的防止恶意攻击和爬虫采集;②容器限流:比如 Tomcat、Nginx 等限流手段,其中 Tomcat 可以设置最大线程数(maxThreads),当并发超过最大线程数会排队等待执行;而 Nginx 提供了两种限流手段:一是控制速率,二是控制并发连接数;③服务端限流:比如我们在服务器端通过限流算法实现限流,此项也是我们本文介绍的重点。合法性验证限流为最常规的业务代码

2021-04-11 22:32:00 36

原创 Dubbo架构以及调用流程

一.Dubbo结构图duubo结构图解释一下这个架构图:Consumer服务消费者,Provider服务提供者。Container服务容器。消费当然是invoke提供者了,invoke这条实线按照图上的说明当然同步的意思了。但是在实际调用过程中,Provider的位置对于Consumer来说是透明的,上一次调用服务的位置(IP地址)和下一次调用服务的位置,是不确定的。这个地方就需要使用注册中心来实现软负载。Register服务提供者先启动start,然后注册register服务。消费订阅subs

2021-04-07 20:15:21 31

原创 一文学会使用CompletableFuture

**前言:**Java 8引入了CompletableFuture以及它的接口CompletionStage作为对Future的增强,它可以让你使用回调驱动的方式表达不同任务的信息流。CompletableFuture用来定义单个任务事件的计算。1.创建 public void completedFutureExample() { CompletableFuture cf = CompletableFuture.completedFuture("test"); asse

2021-04-04 21:26:58 30

原创 JVM垃圾收集算法和垃圾收集器

1.如何判断对象是否存活在进行垃圾回收的时候如何判断对象是否存活呢?(1)引用计数法给对象添加一个计数器,每引用一次计数器+1,失效就-1,任何时候,计数器=0的对象就是没有被引用的对象,可以被回收。但是这种方法,没办法解决对象之间引用的情况,比如对象A引用了对象B,对象B又引用了对象A,所以又有了 跟搜索算法。(2)跟搜索算法 GC ROOT 可达性算法GC Roots的对象为起点,从这些节点向下开始搜索,搜索的路程成为引用连,当一个对象到GC Roots没有任何引用链的时候,该对象可以被认定为

2021-03-31 16:55:09 20

转载 再也不怕被问到分布式锁----分布式锁的几种解决方案

1.什么是分布式锁为了防止分布式系统中的多个进程之间相互干扰,我们需要一种分布式协调技术来对这些进程进行调度。而这个分布式协调技术的核心就是来实现这个分布式锁。1.1 为什么要使用分布式锁假设一个场景:成员变量X是一个有有状态的对象,存在 JVM1、JVM2、JVM3 三个 JVM 内存中,成员变量 X同时都会在 JVM 分配一块内存,三个请求发过来同时对这个变量操作,显然结果是不对的,不是同时发过来,三个请求分别操作三个不同 JVM 内存区域的数据,变量 X 之间不存在共享,也不具有可见性,处理的结

2021-03-28 21:32:29 123

转载 IO(2)---BIO、NIO、AIO编程

1.BIO编程1.1、传统的BIO编程网络编程的基本模型是C/S模型,即两个进程间的通信。服务端提供IP和监听端口,客户端通过连接操作想服务端监听的地址发起连接请求,通过三次握手连接,如果连接成功建立,双方就可以通过套接字进行通信。传统的同步阻塞模型开发中,ServerSocket负责绑定IP地址,启动监听端口;Socket负责发起连接操作。连接成功后,双方通过输入和输出流进行同步阻塞式通信。简单的描述一下BIO的服务端通信模型:采用BIO通信模型的服务端,通常由一个独立的Acceptor线程负责

2021-03-24 21:46:49 19

原创 JVM(三)---调优总结

1.JVM 内存调优对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数。1.Full GC会对整个堆进行整理,包括Young、Tenured和Perm。Full GC因为需要对整个堆进行回收,所以比较慢,因此应该尽可能减少Full GC的次数。2.导致Full GC的原因1)年老代(Tenured)被写满调优时尽量让对象在新生代GC时被回收、让对象在新生代多存活一段时间和不要创建过大的对象及数组避免直接在旧生代创建对象 。2)持久代Pemanet Generation空

2021-03-21 22:19:51 25

原创 JVM(二)---JVM调优

1.利用工具分析JVM运行情况要想合理地分配内存、优化GC,通过前一篇的性能调优过程可以发现,我们至少需要知道如下的一些信息:新生代对象增长的速率,YoungGC的触发频率,YoungGC的耗时,每次YoungGC后存活对象大小,每次YoungGC过后有多少对象进入了老年代,老年代对象增长的速率,FullGC的触发频率,FullGC的耗时等。前面我们是通过分析GC日志或者粗略估算的方式来调优的,现在就利用 jstat 工具来分析下。1、运行示例程序1)如下示例代码这段代码模拟每秒钟在新生代创建20M

2021-03-21 22:17:28 38 2

原创 JVM(一)---调优工具

1.调优工具1.1 JDK工具1.1.1 利用 jps 找出进程jps(Java Virtual Machine Process Status Tool)是JDK 1.5提供的一个显示当前所有java进程pid的命令,简单实用,非常适合在linux/unix平台上简单察看当前java进程的一些简单情况。1)查看Java进程PID【jps -l】左边一列就是Java进程的PID。2)输出传递给JVM的参数【jps -vl】1.1.2 利用 jstat 查看VM统计信息使用 jstat

2021-03-21 22:03:54 33

原创 class加载过程

1.class加载过程java虚拟机把描述类的数据从class文件加载到内存,并对数据进行 校验/准备/解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称作虚拟机的类加载机制。loading -> linking (verification-> preparation -> resolution )-> initializingloading:把class文件load到内存中,采用双亲委派,主要是为了安全性verification:校验class文件是否符

2021-03-17 21:47:57 189 2

原创 RocketMQ实战(3) -事务消息

RocketMQ实战(3) -事务消息干干净净没有故事,一个酷字贯穿一生。springBoot快速整合rabbitMQ。话不多少,上才艺~1.生产者方面1.1 定义监听器------执行本地事务和事务会查:@RocketMQTransactionListener@Slf4jpublic class TransactionListener implements RocketMQLocalTransactionListener { @Override public RocketMQ

2020-10-16 10:05:43 58

空空如也

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人 TA的粉丝

提示
确定要删除当前文章?
取消 删除