当前位置: 首页 > news >正文

php外贸网站模板奔驰宝马游戏网站建设

php外贸网站模板,奔驰宝马游戏网站建设,泛微oa办公系统官网,程序员自己做网站怎么能来钱文章目录 1.谈谈你对Spring的理解2.Spring的常用注解有哪些3.Spring中的bean线程安全吗4.Spring中的设计模式有哪些5.Spring事务传播行为有几种6.Spring是怎么解决循环依赖的7.SpringBoot自动配置原理8.SpringBoot配置文件类型以及加载顺序9.SpringCloud的常用组件有哪些10.说一… 文章目录 1.谈谈你对Spring的理解2.Spring的常用注解有哪些3.Spring中的bean线程安全吗4.Spring中的设计模式有哪些5.Spring事务传播行为有几种6.Spring是怎么解决循环依赖的7.SpringBoot自动配置原理8.SpringBoot配置文件类型以及加载顺序9.SpringCloud的常用组件有哪些10.说一说Feign的工作原理11.说一说Nacos的工作原理12.说一说Ribbon的工作原理和常用负载均衡策略13.Hystrix的作用是什么断路器的工作原理14.解释一下服务雪崩、服务熔断、服务降级15.拦截器和过滤器的区别是什么16.Redis的数据类型和使用场景有哪些17.Redis为什么这么快18.Redis的集群有哪些19.Redis的持久化方式有哪些20.了解过Redis的事务吗21.Redis实现分布式锁的原理是什么22.如何保存Redis数据与DB数据的一致性23.Redis过期删除策略和内存淘汰策略有哪些24.Redis常见的缓存问题和对应的解决方案25.MySQL中char和varchar的区别26.事务的四大特性是什么27.并发事务会带哪些问题28.事务隔离级别有哪些29.索引的创建原则30.索引失效的情况31.如何知道索引是否失效32.常见的数据库存储引擎有哪些33.索引的数据结构是什么34.数据库中的锁有哪些35.数据库的日志类型有哪些36.谈一谈你对SQL优化的经验37.MyBatis中#{}和${}的区别是什么38.使用RabbitMQ如何保证消息不丢失39.如何解决消息的重复消费问题和消息堆积问题40.什么是倒排索引41.ES中的查询关键字有哪些42.HashMap的底层结构和扩容机制43.ConcurrentHashMap的底层结构44.线程池重要参数有哪些任务队列有哪些拒绝策略有哪些45.说一说线程池工作流程46.synchronized和lock的区别47.JVM的垃圾回收算法有哪些48.你们工作中是如何是git的49.说几个常用的运维命令50.说几个常见的vue指令51.项目处理过哪些问题让你记忆深刻如何解决的52.公司有多少人有多少开发人员有多少前端人员有多少产品经理53.公司在哪个城市那个大厦那条街你住在哪里怎么去公司54.项目中遇到的异常有哪些怎么解决这些异常55.为什么离职56.上家薪资构成社保基数57.现在有offer了吗为什么没有去58.加班怎么看 1.谈谈你对Spring的理解 Spring框架为Java应用程序提供了全面的解决方案帮助开发者简化开发流程、提高代码质量和可维护性。IOC和AOP是Spring框架中的两个核心概念。 IOC IOC也叫控制反转是Spring用来解耦的一种设计思想它把对象的控制权从程序员手中反转到Spring手中。在没有IOC之前对象都是程序员在类中主动创建需要哪个创建哪个有了IOC之后对象交给Spring容器创建和管理哪个对象中需要其它对象属性Spring会自动完成依赖注入。 总之IOC可以将对象的创建和对象之间依赖关系的维护交给Spring自动完成。 AOP AOP又叫面向切面编程核心思想是把与业务无关却被业务模块所共同调用的逻辑如事务处理、日志管理封装起来再动态插入到业务模块中。 使用AOP可以减少系统重复代码降低模块间的耦合度有利于扩展和维护Spring AOP是基于动态代理的底层同时支持JDK和CGLIB的代理方式并且会根据被代理类是否有接口自动选择最合适的代理方式。 我们在开发中用到AOP的场景有事务管理、日志、性能监视、安全检查。 2.Spring的常用注解有哪些 常用的Spring注解主要分为下面几大类 用于创建对象的Component、Controller、Service、Repository 标注在自己开发的类上Spring会用注解标注的类创建出对象然后放入容器用于依赖注入的Autowired 标注在属性或属性对应的set方法上Spring会根据被标注属性的类型自动对属性进行赋值和Autowired一起使用用于依赖注入的Qualifier 在同一类型的bean有多个的情况下Spring会根据name进行选择注入用于配置类的Configuration、Bean 标注在配置类中用于声明配置类和向Spring容器中放入一些配置有关的对象用于声明注解扫描的ComponentScan声明Bean的作用域的Scope用于切面编程的AroundPointcut等等 3.Spring中的bean线程安全吗 Spring中的Bean主要分为单例和多例。 ● 每次获取多例对象都会创建新实例线程之间不存在共享Bean问题也就不存在线程安全问题。 ● 单例对象是所有线程共享一个实例就可能会存在线程安全问题。单例对象又分为无状态和有状态。 无状态Bean是只对对象的成员变量进行查询操作不修改成员变量的值所以不存在线程安全问题。有状态Bean需要对Bean中的成员变量进行数据更新操作所以就可能存在线程安全问题。 所以在Spring中只有有状态的单例Bean才会存在线程安全问题。 处理有状态单例Bean的线程安全问题有以下两种方法 1、将Bean的作用域由单例改为多例 2、将需要的可变成员变量保存在ThreadLocal中 ThreadLocal本身具备线程隔离特性相当于为每个线程提供了一个独立的变量副本每个线程只需操作自己的线程变量副本从而解决线程安全问题。 4.Spring中的设计模式有哪些 Spring中常用的设计模式有 工厂模式Spring 使用工厂模式通过 BeanFactory 和 ApplicationContext 创建 Bean 对象单例模式 Spring 中的 Bean 默认都是单例的代理模式 Spring 的 AOP 功能用到了 JDK 的动态代理和 CGLIB 字节码生成技术模板方法用来解决代码重复的问题。比如 RestTemplate、JDBCTemplate、JpaTemplate 等以 Template 结尾的对数据库操作的类它们就使用到了模板模式观察者模式 Spring 事件驱动模型是观察者模式很经典的一个应用。定义对象间一种一对多的依赖关系当一个对象的状态发生改变时所有依赖于它的对象都会得到通知被制动更新如 Spring 中 listener 的实现 ApplicationListener。 5.Spring事务传播行为有几种 事务传播行为是为了解决业务层方法之间互相调用的事务问题。 当事务方法被另一事务方法调用时必须指定事务应该如何传播。 方法可能继续在现有事务中运行也可能开启一个新事务并在自己的事务中运行。 Spring支持7种事务传播行为 必须事务若当前存在事务就加入该事务若当前没有事务就创建一个新的事务必须新事务创建一个新事务若当前存在事务就把当前事务挂起强制事务若当前存在事务就加入该事务若当前没有事务就抛出异常支持事务若当前存在事务就加入该事务若当前没有事务就以非事务的方式继续运行不支持事务以非事务方式运行若当前存在事务则把当前事务挂起强制无事务以非事务方式运行若当前存在事务则抛出异常嵌套事务若当前存在事务就创建一个当前事务的嵌套事务来运行若当前没有事务就创建一个事务 嵌套事务是已存在事务的一个子事务嵌套事务开始执行时将取得一个保存点 若这个嵌套事务失败将回滚到此保存点 嵌套事务是外部事务的一部分只有外部事务结束后它才会被提交 6.Spring是怎么解决循环依赖的 IOC容器解决循环依赖需要用到几个重要成员 singletonObjects一级缓存存放初始化好的 Bean 的集合从此集合中取出来的 Bean 可以立马返回。 earlySingletonObjects二级缓存存放创建好但没有初始化属性的 Bean 的集合它用来解决循环依赖。 singletonFactories三级缓存存放单例 Bean 工厂的集合。 singletonsCurrentlyInCreation存放正在被创建的 Bean 的集合。 IOC 容器解决循环依赖的思路 初始化 Bean 之前将这个 BeanName 放入三级缓存创建 Bean 将准备创建的 Bean 放入 singletonsCurrentlyInCreation 正在创建的 BeancreateNewInstance 方法执行完后执行 addSingletonFactory将这个实例化但没有属性赋值的 Bean 放入二级缓存并从三级缓存中移除进行属性赋值和自动注入时引发关联创建关联创建时检查“正在被创建的 Bean”中是否有即将注入的 Bean。如果有检查二级缓存中是否有当前创建好但没有赋值初始化的 Bean。如果没有检查三级缓存中是否有正在创建中的 Bean。至此一般会有将这个 Bean 放入二级缓存并从三级缓存中移除之后 Bean 被成功注入最后执行 addSingleton将这个完全创建好的 Bean 放入一级缓存从二级缓存和三级缓存移除并记录已经创建了的单例 Bean 7.SpringBoot自动配置原理 Springboot自动装配是基于注解编程和约定优于配置的思想来设计的。 自动装配就是自动把其他组件中的Bean装载到IOC容器中不需要开发人员再去配置文件中添加大量配置。 只需在SpringBoot的启动类上添加SpringBootApplication的注解就能开启自动装配。 SpringBootApplication开启自动装配底层最重要的一部分是EnableAutoConfiguration这个注解来实现的它的作用是 读取所有包中两个指定配置文件中的所有自动配置类(xxxxAutoConfiguration)这些值必须声明为Spring的配置类也就是在类中需要向Spring容器放入对象为了防止非当前所需的组件进入到容器配置类中需要使用Conditional注解来声明配置成立的必要条件 8.SpringBoot配置文件类型以及加载顺序 SpringBoot支持的配置文件类型有properties、yaml 、yml等。 bootstrap.yml和application.yml是SpringBoot支持的两个核心配置文件区别在于 boostrap比applicaton优先加载在应用程序上下文的引导阶段生效且里面的属性不能被覆盖。一般在SpringCloud Config或者Nacos中会用到它。 application.yml用于SpringBoot项目的自动化配置我们会把自己项目的业务配置项写在这里面。 9.SpringCloud的常用组件有哪些 SpringCloud 是一系列框架的有序集合。它利用 SpringBoot 的开发便利性巧妙地简化了分布式系统基础设施的开发。 如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等都可以用 SpringBoot 的开发风格做到一键启动和部署。 早期我们一般认为的Spring Cloud五大组件是 ● Eureka : 注册中心 ● Ribbon : 负载均衡 ● Feign : 远程调用 ● Hystrix : 服务熔断 ● Zuul/Gateway : 网关 随着SpringCloudAlibba在国内兴起 , 我们项目中使用了一些阿里巴巴的组件 ● 注册中心/配置中心 Nacos ● 负载均衡 Ribbon ● 服务调用 Feign ● 服务保护 sentinel ● 服务网关 Gateway 10.说一说Feign的工作原理 Feign是SpringCloud技术栈中用于远程调用的一个HTTP客户端主要作用是将远程服务调用和本地方法调用格式统一。 Feign的工作步骤如下 首先在SpringBoot的启动类上添加EnableFeignClients 注解开启对Feign的支持当程序启动时会扫描所有标有FeignClient的注解的类并且将这些信息注入Spring IOC 容器中当定义的 Feign 接口中的方法被调用时通过JDK的代理方式来生成具体的 RequestTemplateRequestTemplate对象封装了 HTTP 请求需要的全部信息如请求参数名请求方法等信息然后RequestTemplate生成 Request并将Request交给Client去处理这里的 Client 可以是 JDK 原生的 URLConnection、Apache 的 HttpClient等最后Client被封装到LoadBalanceClient类这个类结合Ribbon负载均衡发起服务之间的调用 11.说一说Nacos的工作原理 Nacos是SpringCloudAlibaba技术栈的一项技术在项目中主要用作服务注册中心和服务配置中心。 ● Nacos作为服务注册中心具备下面这些能力 1.服务注册服务提供者会将自己的地址信息注册到Nacos中在nacos中形成一张服务清单 2.服务发现服务消费者会从Nacos中查询服务提供者的信息并且缓存到本地并且每隔30s更新一次 3.当服务提供者的地址发生变化之后Nacos也会主动推送最新的地址信息给消费者 4.服务续约服务提供者会间隔一定时间就给Nacos发送心跳表明自己在线 5.服务剔除当nacos一段时间内接收不到服务微服务的续约请求时或者收到微服务的下线请求时就会将服务地址从服务清单中删除 ● Nacos作为服务配置中心的原理 Nacos允许微服务将一些经常改动的配置项保存到Nacos中然后在本地的bootstrap.yml中指定远程配置的位置信息Nacos的配置发生变化之后会主动推送给微服务微服务进行热更新Nacos还支持使用多环境、命名空间的方式实现多套配置文件的共存 12.说一说Ribbon的工作原理和常用负载均衡策略 我们项目中使用的是Feign来进行远程微服务的调用Feign底层集成了Ribbon大体使用流程如下 当请求发出的时候会被Ribbon的负载均衡拦截器所拦截Ribbon会提取请求路径中微服务的名称然后去服务治理中心中查找微服务的对应的服务地址Ribbon会使用配置的负载均衡策略从众多地址中选择一个进行调用 Ribbon官方提供了7种负载均衡策略轮询策略按照一定的顺序依次调用服务实例权重策略根据每个服务提供者的响应时间分配一个权重响应时间越长权重越小被选中的可能性也就越低。它的实现原理是刚开始使用轮询策略并开启一个计时器每一段时间收集一次所有服务提供者的平均响应时间然后再给每个服务提供者附上一个权重权重越高被选中的概率也越大。随机策略从服务提供者的列表中随机选择一个服务实例最小连接数策略遍历服务提供者列表选取连接数最小的一个服务实例。如果有相同的最小连接数那么会调用轮询策略进行选取。重试策略按照轮询策略来获取服务如果获取的服务实例为 null 或已经失效则在指定的时间之内不断地进行重试来获取服务如果超过指定时间依然没获取到服务实例则返回 null。可用性敏感策略先过滤掉非健康的服务实例然后再选择连接数较小的服务实例区域敏感策略根据服务所在区域zone的性能和服务的可用性来选择服务实例在没有区域的环境下该策略和轮询策略类似。 13.Hystrix的作用是什么断路器的工作原理 在微服务架构中会拆分出很多服务服务间存在复杂的调用关系这些服务一旦出现失败的情况就会导致服务雪崩 Hystrix就是来防止服务雪崩的工具它具有服务降级服务熔断服务隔离监控等防止雪崩的技术。 它有四种防雪崩手段 服务隔离隔离服务之间相互影响服务监控在服务发生调用时会将每秒请求数、成功请求数等运行指标记录下来服务熔断接口调用失败就会进入调用接口提前定义好的一个熔断的方法返回错误信息服务降级接口调用失败就调用本地的方法返回一个空 断路器状态机包括三个状态 1、 closed关闭状态断路器放行所有请求并开始统计异常比例、慢请求比例。超过阈值则切换到open状态 2、open打开状态服务调用被熔断访问被熔断服务的请求会被拒绝快速失败直接走降级逻辑。Open状态5秒后默认值会进入 3、half-open状态half-open半开状态放行一次请求根据执行结果来判断接下来的操作 ○ 请求成功则切换到closed状态 ○ 请求失败则切换到open状态 14.解释一下服务雪崩、服务熔断、服务降级 服务熔断当下游服务因访问压力过大而响应变慢或失败为保证整个服务的可用性上游服务会暂时切断对下游服务的调用。这种牺牲局部保全整体的措施就叫做熔断。 服务降级就是为服务提供一个托底方案一旦服务无法正常调用就使用托底方案。 服务雪崩服务雪崩是指由于某个服务故障或不可用导致其他依赖于该服务的服务也不可用。 15.拦截器和过滤器的区别是什么 拦截器和过滤器都可以实现请求的拦截处理不同点有下面几个 ● 技术栈所属不同过滤器属于JavaWeb技术依赖Servlet容器而拦截器是属于Spring的技术 ● 实现原理不同拦截器是基于Java的反射机制而过滤器是基于函数回调 ● 拦截范围不同过滤器可以拦截所有请求而拦截器主要是针对发往controller请求 ● 拦截位置不同过滤器在前端控制器前拦截行而拦截器在前端控制器后拦截 16.Redis的数据类型和使用场景有哪些 Redis最常见的数据类型有5种分别是String、List、Hash、Set、ZSet下面给您详细介绍一下 String简单的 key-value 类型最大能存储512MB数据。场景计数、缓存文章标题、微博内容等 List底层是链表特点是增删容易随机访问困难。场景发布与订阅或者说消息队列 Hash类似于Java中的HashMap适合存储对象。场景系统中对象数据的存储 Set是一种无序集合可以方便的求交、并、差集。 场景共同关注、共同粉丝、共同喜好等功能 ZSet相比于set来讲多了1个权重参数 score元素会按照score进行排序。场景各种排行榜弹幕消息 17.Redis为什么这么快 Redis之所以运行速度快主要是因为: 纯内存操作Redis的绝大部分请求是纯内存操作非常快单线程Redis的核心部分是单线程运行的避免了不必要的上下文切换也不存在线程切换导致的 CPU消耗使用 I/O 多路复用模型和非阻塞 IO 18.Redis的集群有哪些 Redis中提供的集群主要有三种分别是主从、哨兵和分片集群 主从集群主要用来解决Redis的并发问题一般是一个主节点负责数据写入多个从节点负责数据读取主节点的数据实时同步给从节点哨兵集群主要用来解决Redis的高可用问题哨兵会监控集群中节点的状态并在主节点出现问题时重新选主分片集群主要用来解决Redis的海量数据存储问题它要求有多个主节点写入的数据会经过计算落到其中一个上 在计算过程中Redis引入了哈希槽的概念Redis集群有16384个哈希槽每个 key通过CRC16校验后对16384取模来决定放置哪个槽 分片集群的每个节点负责一部分 hash 槽就可以计算出一个key会出现在哪个节点上了查询的时候也是同时的方式来定位 19.Redis的持久化方式有哪些 Redis是基于内存的数据存储为了保证数据安全需要把内存中的数据备份到磁盘上官方提供了两种数据持久化的方式分别是RDB和AOF。 RDB采用定期更新的方式它会定期把Redis中的数据生成快照同步到磁盘上磁盘上保存的是Redis的内存快照。 优点数据文件相比于AOF较小数据恢复速度较快 缺点耗时并且存在丢失数据的风险 AOF是将Redis所执行过的所有写指令都记录到磁盘上在下次Redis重启时只需要将指令重写一遍就可以了。 优点数据丢失的风险大大降低了 缺点数据文件的大小相比于rdb较大而且数据恢复的时候速度较慢 我们公司同时开启RDB和AOF持久化机制这样的好处是 在Redis重启时先使用AOF日志进行恢复然后再使用RDB快照进行备份将AOF的appendfsync 参数为 everysec保证每秒将AOF缓冲区中的写操作同步到 AOF 文件中提高数据的持久化能力定期进行RDB快照的备份以便在需要时进行全量数据恢复 这样配置可以充分利用RDB和AOF两种持久化机制的优势提高数据可靠性和恢复能力。 20.了解过Redis的事务吗 Redis中本身没有事务的概念但它有几个命令组合起来能实现类似于事务的效果。 它的本质是一组命令的集合。 用到的命令主要有5个分别是 MULTI组装一个事务EXEC执行一个事物DISCARD取消一个事务WATCH用来监视一些key一旦这些key在事务执行之前被改变就取消事务的执行UNWATCH取消 WATCH 命令对所有key的监视 总结说Redis事务就是一次性、顺序性、排他性地执行一个队列中的一系列命令。 Reids中单条命令是原子性执行的但事务不保证原子性且没有回滚。 21.Redis实现分布式锁的原理是什么 Redis实现分布式锁主要利用Redis的setnx命令。setnx是SET if not exists(如果不存在就SET)的简写。 上面这几个命令就是最基本的用来完成分布式锁的命令。 加锁:使用setnx key value命令若key不存在设置value(加锁成功)。若已存在lock(也就是有客户端持有锁了)设置失败(加锁失败)。 解锁:使用del命令通过删除键值释放锁。释放锁之后其他客户端可以通过setnx命令进行加锁。 22.如何保存Redis数据与DB数据的一致性 保证Redis和MySQL数据一致性的常见方案有三种 同步双写程序更新完MySQL后立即同步更新redis 异步监听通过Canal(通道)监听MySQL的binlog日志然后再通过程序将变化的数据更新到 Redis MQ异步程序更新完MySQL后投递一条消息到MQ中然后再通过一个程序监听MQ获取到消息然后更新Redis 23.Redis过期删除策略和内存淘汰策略有哪些 过期删除策略 Redis的过期删除策略 是 当Redis中的key过期后何时进行删除的处理方案常用的删除策略有两个 ● 惰性删除只在取出 key 的时候才对数据进行过期检查过期了就删除 ● 定期删除每隔一段时间抽取一批 key执行删除过期 key 操作 两者相比定期删除对内存更加友好惰性删除对 CPU 更加友好。 Redis 采用的是定期删除惰性/懒汉式删除。 内存淘汰策略 Redis的内存淘汰策略 是 当Redis的内存已存满又有新的数据需要保存时的处理方案官方提供的淘汰策略有八种 no-eviction禁止驱逐数据内存不足以容纳新写入数据时新写入操作会报错。volatile-lru从已设置过期时间的数据集中选择最近最少使用的数据淘汰volatile-ttl从已设置过期时间的数据集中选择将要过期的数据淘汰volatile-random从已设置过期时间的数据集中任意选择数据淘汰volatile-lfu从已设置过期时间的数据集中挑选最不经常使用的数据淘汰allkeys-lru在所有的数据集中选择最近最少使用的数据淘汰allkeys-random在所有的数据集中任意选择数据淘汰allkeys-lfu在所有的数据集中选择最不经常使用的数据淘汰 24.Redis常见的缓存问题和对应的解决方案 缓存穿透解决方案 在我们的项目中会将缓存放到数据库前面查询的时候先查缓存缓存有了就不用再去查数据库了这样可以大大减轻数据库的访问压力。 缓存穿透指的是请求一直在查询一个数据库中不存在的数据缓存中没有请求就会到达数据库数据库也没有就没法缓存。 所以每一次请求都会直接到数据库中查询这就极有可能导致数据库被压垮。 常用的解决方案有两个 查询返回的数据为空仍把这个空结果进行缓存但过期时间尽量设置稍短一些使用布隆过滤器将所有可能存在的数据哈希到一个足够大的 bitmap 中一个一定存在的数据会被这个 bitmap 拦截掉从而避免了对数据库的查询 缓存击穿解决方案 在我们的项目中会将缓存放到数据库前面查询的时候先查缓存缓存有了就不用再去查数据库了这样可以大大减轻数据库的访问压力。 缓存击穿指的是对于一个设置了过期时间的key在其缓存失效的瞬间有大量的请求访问这个它这些请求在缓存找不到就会直接到数据导致数据库被压垮。 常用的解决方案有两个 使用互斥锁当缓存失效时不立即去数据库查询而是先去获取一把全局锁那个线程获取到了就去数据库查询获取不到的就等待重试查询缓存。修改设置key有效期的逻辑大体如下 在设置key的时候不给它设置过期时间而是单独设置一个过期时间字段一块存入缓存中 当查询的时候从redis取出数据后判断时间是否过期如果过期则开通另外一个线程进行数据同步当前线程正常返回数据。 两种方案对比 缓存雪崩解决方案 在我们的项目中会将缓存放到数据库前面查询的时候先查缓存缓存有了就不用再去查数据库了这样可以大大减轻数据库的访问压力。 缓存雪崩指的是大量的key在某一时刻同时失效这样大量的请求全部转发到DBDB 瞬时压力过重雪崩。 解决方案也很简单就是在设置key的过期时间的时候尽量加一些随机值这样缓存过期时间的重复率就会降低。 25.MySQL中char和varchar的区别 char和varchar是MySQL中的字符串类型区别有下面几方面 最大长度char最大长度是255字符varchar最大长度是65535个字节占用长度char是定长的不足的部分用隐藏空格填充varchar是不定长的空间使用char会浪费空间varchar会更加节省空间查找效率char查找效率会很高varchar查找效率会更低 因此我们如果存储固定长度的列例如身份证号、手机号建议使用char。 其它不定长度的建议使用varchar使用varchar的时候也要尽量让声明长度贴近实际长度。 26.事务的四大特性是什么 事务的四大特性指的是原子性、一致性、隔离性、持久性 ● 原子性事务是最小的执行单位不允许分割同一个事务中的所有命令要么全部执行要么全部不执行 ● 一致性事务执行前后数据的状态要保持一致例如转账业务中无论事务是否成功转账者和收款人的总额应该是不变的 ● 隔离性并发访问数据库时一个事务不被其他事务所干扰各并发事务是独立执行的 ● 持久性一个事务一旦提交对数据库的改变应该是永久的即使系统发生故障也不能丢失 27.并发事务会带哪些问题 并发事务下可能会产生如下的问题 ● 脏读一个事务读取到了另外一个事务没有提交的数据 ● 不可重复读一个事务读取到了另外一个事务修改的数据 ● 幻读虚读一个事务读取到了另外一个事务新增的数据 28.事务隔离级别有哪些 事务隔离级别是用来解决并发事务问题的方案不同的隔离级别可以解决的事务问题不一样 ● 读未提交 允许读取尚未提交的数据可能会导致脏读、幻读或不可重复读 ● 读已提交 允许读取并发事务已提交的数据可以阻止脏读但是幻读或不可重复读仍有可能发生 ● 可重复读 对同一字段的多次读取结果都是一致的除非数据是被本身事务自己所修改可以阻止脏读和不可重复读但幻读仍有可能发生 ● 可串行化 所有的事务依次逐个执行这样事务之间就完全不可能产生干扰该级别可以防止脏读、不可重复读以及幻读。 上面的这些事务隔离级别效率依次降低安全性依次升高如果不单独设置MySQL默认的隔离级别是可重复读 29.索引的创建原则 索引可以大幅度提高查询的效率但不是所有的字段都要加也不是加的越多越好因为索引会占据磁盘空间也会影响增删改的效率 我们在建立索引的时候应该遵循下面这些原则 主键字段、外键字段应该添加索引经常作为查询条件、排序条件或分组条件的字段需要建立索引经常使用聚合函数进行统计的列可以建立索引经常使用多个条件查询时建议使用组合索引代替多个单列索引 除此之外下面这些情况不应该建立索引数据量小的表不建议添加索引数据类型的字段是TEXT、BLOB、BIT等数据类型的字段不建议建索引不要在区分度低的字段建立索引比如性别字段、年龄字段等 30.索引失效的情况 索引失效指的是虽然在查询的列上添加了索引但是某些情况下查询的时候依旧没有用到索引常见的情况有 使用like关键字时模糊匹配使用开头将导致索引失效使用连接条件时如果条件中存在没有索引的列会导致索引失效在索引列上进行计算、函数运算、类型转换将导致索引失效使用 !、not in、is null、is not null时会导致索引失效使用联合索引时没有遵循最左匹配原则会导致索引失效 31.如何知道索引是否失效 MySQL中自带了一个关键字叫explain它可以加在一个sql的前面来查看这条sql的执行计划 在执行计划中我们主要观察两列的结果一列是type一列是extra 第一个type是重要的列显示本次查询使用了何种类型常见的值从坏到好依次为all、index、range、ref、eq_ref 、const、system ● all表示全表扫描数据文件返回符合要求的记录 ● index表示全表扫描索引文件返回符合要求的记录 ● range表示检索指定范围的行常见于使用betweeninlike等运算符的查询中 ● ref表示两表查询时驱动表可能返回多行数据也就是查询条件在主表中是加了一个普通索引 ● eq_ref表示两表查询时驱动表只返回一行数据也就是查询条件在主表中是唯一的 ● const表示索引一次就能得到结果一般是使用唯一索引或者主键作为查询条件 ● system表示表中仅有一行数据很少见到 我们在优化的时候尽量优化到range级别以上 除了type之外我们需要关注一下extra列它表示执行状态说明 ● 要保证此列不要出现using filesort、using temporary等使用临时表或外部文件的情况 ● 如果出现using index最好了它表示列数据仅仅使用了索引中的信息而没有回表查询 32.常见的数据库存储引擎有哪些 MyISAM和InnoDB是目前MySQL中最为流行的两种存储引擎它们的区别有这几方面 MyISAM不支持事务每次操作都是原子的InnoDB支持事务支持事务的四种隔离级别MyISAM不支持外键InnoDB支持外键MyISAM仅仅支持表级锁即每次操作是对整个表加锁InnoDB支持行级锁因此可以支持写并发MyISAM属于非聚集性索引它的数据和索引不在同一个文件中InnoDB属于聚集性索引它的数据和索引在同一个文件中MyISAM中主键和非主键索引的数据部分都是存储的文件的指针InnoDB主键索引的数据部分存储的是表记录非主键索引的数据部分存储的是主键值 33.索引的数据结构是什么 在MySQL中索引使用的数据结构是BTreeB树是基于B树的变种它具有B树的平衡性而且树的高度更低 ● B树非叶子节点不存数据只存索引因此其内部节点相对B树更小树的高度更小查询产生的I/O更少 ● B树查询效率更高B树使用双向链表串连所有叶子节点区间查询效率更高 ● B树查询效率更稳定B树每次都必须查询到叶子节点才能找到数据而B树查询的数据可能不在叶子节点也可能在这样就会造成查询的效率的不稳定 34.数据库中的锁有哪些 MySQL中的锁从不同维度可以分为不同的种类 从锁的粒度上可以分为表锁和行锁 表锁指的是会锁定修改数据所在的整个表开销小加锁快锁定粒度大发生锁冲突概率高 行锁指的是会锁定修改数据所在的行记录开销大加锁慢锁定粒度小发生锁冲突概率低从锁的排他性上分为共享锁和排他锁 共享锁指的是当一个事务针对同一份数据加上共享锁之后另一个事务也可以再往上加一把共享锁也可以读数据但是不能改 对索引列加共享锁锁定的是一行数据对非索引列加共享锁锁定的是整表数据 排他锁指的的是当一个事务针对同一份数据加上排他锁之后另一个事务只能读数据不能改也不能再上其它任务锁还有两种概念上的锁是悲观锁和乐观锁 悲观锁是指一个事务在修改数据的时候总是认为别人也会修改此数据所以强制要使用锁来保证数据安全 乐观锁是指一个事务在修改数据的时候总是认为别人不会修改此数据因为不加任何锁 这种情况下万一在当前事务修改的时候数据被其它事务也修改了机会出现问题此时常用的方案是 给数据表中添加一个version列每次更新后都将这个列的值加1读取数据时将版本号读取出来 在执行更新的时候会先比较版本号如果相同则执行更新如果不相同说明此条数据已经发生了变化就放弃更新或重试 35.数据库的日志类型有哪些 MySQL的很多功能都是依靠日志来实现的比如事务回滚数据备份主从复制等等常见的日志有下面几个 binlog归档日志 负责记录对数据库的写操作一般用在主从复制过程中记录日志从库拷贝此日志做重放实现数据同步redolog重做日志 用于确保事务的持久性。防止在发生故障的时间点尚有脏页未写入磁盘 在重启 mysql 服务的时候根据 redo log 进行重做从而达到事务的持久性这一特性undo log 回滚日志 保存了事务发生之前的数据的一个版本可以用于回滚 36.谈一谈你对SQL优化的经验 我在企业中优化Sql大体分为三步 查找问题sql主要手段是开启mysql的慢查询日志它会将执行时间较长的sql记录记录下来找到sql之后我会分析出现问题的原因原因很多主要字段类型选择错误、sql语句效率低、索引失效等等根据问题不同我会再去定具体的解决方案 简单给您说几个常见的吧确定选择的引擎是否合适 myisam适合于查询为主增删较少无事务要求的数据表 Innodb适用于有事务处理或者包括很多的更新和删除的数据表表设计是否合理 单表不要有太多字段建议在20以内 合理的加入冗余字段可以提高查询速度确定字段的数据类型是否合适 数值型字段的比较比字符串的比较效率高得多字段类型尽量使用最小、最简单的数据类型 设置合适的字符串类型char和varcharchar定长效率高varchar可变长度效率稍低varchar的长度只分配真正需要的空间 尽量使用TIMESTAMP而非DATETIME尽量设计所有字段都得有默认值尽量避免null确定sql的书写是否有的题 SELECT语句务必指明字段名称避免直接使用select * SQL语句中IN包含的值不应过多 可以用内连接就尽量不要使用外连接 使用连接连接查询来代替子查询 使用联合(UNION)来代替手动创建的临时表表数据比较多的时候是否添加了合适的索引 表的主键、外键必须有索引 经常出现在where子句中的字段特别是大表的字段应该建立索引 经常用于排序、分组的字段应当建立索引 加上索引之后还应该使用Explain来确认索引是否生效如果上面的几项都没有问题那可能就是因为服务器性能或者数据量过大导致的查询慢此时可以考虑读写分离 也就是我们搭建一个MySQL的主从集群让1个主节点负责写入数据多个从节点负责查询数据以分摊查询压力 37.MyBatis中#{}和${}的区别是什么 在Mybatis中#{}和${}都可以用于在sql语句中拼接参数但是在使用方面有很多的区别 处理方式不同 表示的是字符串拼接 M y b a t i s 在处理它时会直接将 {}表示的是字符串拼接Mybatis在处理它时会直接将 表示的是字符串拼接Mybatis在处理它时会直接将{}替换成变量的值 而#{}是预编译处理Mybatis在处理它时会将sql中的#{}替换为?号然后底层使用JDBC的预编译对象来赋值安全性不同${}存在SQL注入问题#{}可以有效的防止SQL注入效率不同KaTeX parse error: Expected EOF, got # at position 23: …l到数据库每次都要重新编译而#̲{}处理的sql只需要编译一次…{}当然这也不是说 就没有使用场景比如如果 s q l 中需要动态传递表名或者字段名那就只能使用 {}就没有使用场景 比如如果sql中需要动态传递表名或者字段名那就只能使用 就没有使用场景比如如果sql中需要动态传递表名或者字段名那就只能使用{}了 38.使用RabbitMQ如何保证消息不丢失 消息从生产者发送到消费者接收会经历多个过程 , 其中的每一步都可能导致消息丢失 大体可以分为这样几种情况: 消息发送到交换机丢失消息从交换机路由到队列丢失消息保存到队列中丢失消费者消费消息丢失 针对每一步RabbitMQ分别给出了解决方案消息发送到交换机丢失发布者确认机制 消息发送到交换机失败会向生产者返回失败原因生产者通过回调接收发送结果如果发送失败重新发送或者记录日志人工介入消息从交换机路由到队列丢失发布者回执机制 消息从交换机路由到队列失败会向生产者返回失败原因 生产者通过回调接收回调结果如果发送失败重新发送或者记录日志人工介入消息保存到队列中丢失MQ持久化 RabbitMQ运行开启交换机持久化、队列持久化、消息持久化以保证消息在传输过程中不会丢失消费者消费消息丢失消费者确认机制 消费者确认机制指的是只有消费者一方确认消息消费成功了mq才删除消息否则就会重新发送消息给消费者 通过RabbitMQ本身所提供的机制基本上已经可以保证消息不丢失, 但是因为一些特殊的原因还是会发送消息丢失问题 , 例如 : 回调丢失 , 系统宕机, 磁盘损坏等 , 这种概率很小 , 但是如果想规避这些问题 , 进一步提高消息发送的成功率, 也可以通过程序自己进行控制。 设计一个消息状态表 , 主要包含 : 消息id , 消息内容 , 交换机 , 消息路由key , 发送时间, 签收状态等字段 , 发送方业务执行完毕之后 , 向消息状态表保存一条消息记录, 消息状态为未签收 , 之后再向MQ发送消息 , 消费方接收消息消费完毕之后 , 向发送方发送一条签收消息 , 发送方接收到签收消息之后 , 修改消息状态表中的消息状态为已签收 ! 之后通过定时任务扫描消息状态表中这些未签收的消息 , 重新发送消息, 直到成功为止 , 对于已经完成消费的消息定时清理即可 ! 39.如何解决消息的重复消费问题和消息堆积问题 消息的重复消费问题 在使用RabbitMQ进行消息收发的时候如果发送失败或者消费失败会自动进行重试那么就有可能会导致消息的重复消费 解决方案 ● 每条消息设置一个唯一的标识id ● 幂等方案 ○ tokenredis ○ 分布式锁 ○ 数据库锁悲观锁、乐观锁 解决消息堆积有几种种思路 提高消费者的消费能力例如使用多线程消费增加消费者数量提高消费速度可以使用ork队列模式设置多个消费者消费消费同一个队列中的消息扩大队列容积提高堆积上限使用RabbitMQ惰性队列接收到消息后直接存入磁盘而非内存消费者要消费消息时才会从磁盘中读取并加载到内存 40.什么是倒排索引 倒排索引是搜索引擎的核心它是一种像数据结构一样的散列图可将用户从单词导向文档或网页。主要目标是快速从数百万文件中查找数据 倒排索引主要体现在文档的保存和查询流程中 ● 保存文档时会先根据文档进行分词然后使用分好的词条作为key进行排序然后将文档的标识作为value进行存储 ● 查询文档时也会先对查询关键字进行分词然后根据分好的词条直接定位相关文档再做结果的合并 41.ES中的查询关键字有哪些 在ES中用于声明查询条件的关键字主要有 ● match_all查询所有 ● match、multi_match全文检索 ● term精准词条查询 ● range范围查询 ● bool、must、must_not、should、filter复合查询 还有一些跟地理位置、相关性算分相关的 42.HashMap的底层结构和扩容机制 HashMap底层数据结构是哈希表哈希表在JDK1.8之前是数组链表实现在JDK1.8之后是数组链表红黑树实现的 下面我以map中存储对象的流程给您说一下它的实现原理吧 当我们创建一个HashMap的时候JDK就会在内存中创建一个长度为16的数组当我们调用put方法像HashMap中保存一个元素的时候它会先调用key的hashCode方法计算出key的hash值 然后使用得到hash值对数组长度取余找出当前对象的元素在数组中的位置接下来它会判断算出的位置上是否有元素如果没有就会将此元素直接存储到当前位置上 如果算出的位置上有元素或者是有链表它会再调用key的equals方法跟存在元素的key做比较 如果有一个比较得到的结果为true则会进行值的覆盖如果都为false则会将元素追加在链表的末尾 当然为了降低Hash冲突和链表长度HashMap还做了一些优化当元素的数量超过数组大小与加载因子的乘积的时候就会执行扩容扩容为原来的2倍并将原来数组中的键重新进行hash运算然后分配到新数组中当链表的长度8并且数组长度64的时候链表就会转换为红黑树当红黑树结点数小于6时将再次转回为链表。 HashMap的扩容机制是怎样的 HashMap的扩容机制是指当HashMap中的元素个数超过数组长度乘以负载因子时就会重新分配一个更大的数组并将原来的元素重新计算哈希值并插入到新的数组中。 在JDK1.8中底层是调用resize方法实现扩容的它的默认做法是当元素个数超过数组长度的0.75倍时触发扩容每次扩容的时候都是扩容为原来的2倍 扩展后Node对象的位置要么在原位置要么移动到原偏移量两倍的位置 43.ConcurrentHashMap的底层结构 ConcurrentHashMap的底层结构是由一个Segment数组和HashEntry数组组成的。 Segment是一种可重入锁用来控制对HashEntry数组的访问。每个Segment维护着一个HashEntry数组这样可以将整个Map分成多个Segment每个Segment都可以独立地进行扩容和操作从而提高并发性能。 在Java 8及以上版本ConcurrentHashMap底层结构发生了改变使用了Node数组和红黑树来替代Segment数组和HashEntry数组以提高并发性能和减少内存占用。 44.线程池重要参数有哪些任务队列有哪些拒绝策略有哪些 线程池在创建的时候最大支持传入7个参数分别是 核心线程数最大线程数临时线程的空闲时间临时线程会在空闲这段时间后临时线程的空闲时间单位工作队列用来保存等待执行的任务的threadFactory设置创建线程的工厂handler线程池的拒绝策略 任务队列有哪些 阻塞队列指的是当线程中核心线程数已满新任务到达时存储线程的队列常见的有下面几种 ● ArrayBlockingQueue基于数组结构的有界阻塞队列 ● LinkedBlockingQueue基于链表结构的有界阻塞队列 ● PriorityBlockingQueue具有优先级别的阻塞队列 ● SynchronousQueue不存储元素的阻塞队列每个插入操作都必须等待一个移出操作 拒绝策略有哪些 拒绝策略是指将任务添加到线程池中时线程池拒绝该任务所采取的相应策略官方提供的有4种 ● AbortPolicy直接抛出异常默认策略 ● CallerRunsPolicy用调用者所在的线程来执行任务 ● DiscardOldestPolicy丢弃阻塞队列中靠最前的任务并执行当前任务 ● DiscardPolicy直接丢弃任务 45.说一说线程池工作流程 当我们提交一个任务到线程池中线程池的处理流程如下 首先判断线程池里的核心线程是否都在执行任务如果不是则创建一个新的工作线程来执行任务。如果核心线程都在执行任务则判断工作队列是否已满如果没满则将新提交的任务存储在这个工作队列里。如果工作队列满了则判断线程数是否小于最大线程数如果是则创建临时线程直接执行任务如果线程数已经到达了最大线程数则会执行对应的拒绝策略逻辑 46.synchronized和lock的区别 synchronized是Java中的关键字Lock是一个接口synchronized关键字可以直接修饰方法也可以修饰代码块而lock只能修饰代码块synchronized在发生异常时会自动释放线程占有的锁因此不会导致死锁现象发生 Lock在发生异常时如果没有主动通过unLock()方法去释放锁则很可能造成死锁现象因此使用Lock时需要在finally块中释放锁Lock可以让等待锁的线程响应中断而synchronized却不行使用synchronized时等待的线程会一直等待下去不能够响应中断在性能上来说如果竞争资源不激烈两者的性能是差不多的而当竞争资源非常激烈时即有大量线程同时竞争此时Lock的性能要远远优于synchronized 47.JVM的垃圾回收算法有哪些 目前JVM中的垃圾回收算法主要有四个分别是标记清除算法、标记-整理算法、复制算法和分代收集算法 标记清除算法是将垃圾回收分为2个阶段分别是标记和清除 它会先使用根据可达性分析算法找到垃圾资源进行标记然后对这些标记为可回收的内容进行垃圾回收 这种算法的主要不足有两个 ○ 效率问题标记和清除阶段都要遍历多有对象并且在GC时需要停止应用程序对于交互性要求比较高的应用而言这个体验是非常差的 ○ 空间问题对象被回收之后会产生大量不连续的内存碎片当需要分配较大对象时由于找不到合适的空闲内存而不得不再次触发垃圾回收动作标记整理算法也是将垃圾回收分为2个阶段分别是标记和整理清除 它的第一阶段也是会先将存活的对象先标记出来 不一样的地方在于第二阶段它会将所有存活的对象向前移动放在一起然后将无用空间回收这样就会出现连续的可用空间了 所以它解决了空间碎片问题但是效率低的问题依旧存在复制算法将原有的内存空间一分为二每次只用其中的一半 在垃圾回收时将正在使用的对象复制到另一个内存空间中然后将当前内存空间清空交换两个内存的角色完成垃圾的回收。 这种算法的缺点在于分配2块内存空间在同一个时刻只能使用一半内存使用率较低分代收集算法它会将整个堆内存分成几部分空间每个空间中放入不同类型的对象然后各自适合的算法回收 在JDK8时堆被分为了两份新生代和老年代默认空间比例为1:2 对于新生代内部又被分为了三个区域Eden区S0区S1区默认空间比例为811 它的基本工作机制是 当创建一个对象的时候这个对象会被分配在新生代的Eden区当Eden区要满了时候触发MinorGC 当进行MinorGC后此时在Eden区存活的对象被移动到S0区并且当前对象的年龄会加1清空Eden区 当再一次触发MinorGC的时候会把Eden区中存活下来的对象和S0中的对象移动到S1区中这些对象的年龄会加1清空Eden区和S0区 当再一次触发YoungGC的时候会把Eden区中存活下来的对象和S1中的对象移动到S0区中这些对象的年龄会加1清空Eden区和S1区 对象的年龄达到了某一个限定的值默认15岁那么这个对象就会进入到老年代中除此之外大对象也会直接放入老年代空间 当老年代满了之后触发FullGC**。**FullGC同时回收新生代和老年代 在上述过程中新生代中的对象存活率比较低所以选用复制算法老年代中对象存活率高所以使用标记-整理算法 小细节 当对新生代产生GCMinorGC老年代代产生GCMajor GC 新生代和老年代产生FullGC Minor GC非常频繁一般回收速度也很快Major GC一般会伴随一次Minor GCMajor GC的速度要慢很多一般要比Minor GC慢10倍 占用内存较大的对象对于虚拟机内存分配是一个坏消息虚拟机提供了一个-XX:PretenureSizeThreshold让大于这个设置的对象直接存入老年代 虚拟机给每个对象定义了一个Age年龄计数器对象在Eden中出生并经过第一次Minor GC后仍然存活年龄1此后每熬过一次Minor GC则年龄1 当年龄增加到一定程度(默认15岁)就会晋升到老年代。可通过参数设置晋升年龄 -XX:MaxTenuringThreshold 48.你们工作中是如何是git的 我在工作中对于git的使用可分为以下几个步骤 首先每天上班之后我会从公司远程仓库中进行拉取pull以保证本地项目和远程仓库项目进度一致 然后在本地的开发分支上新建一个当天的分支进行代码开发 开发过程中一般在完成某功能或某一模块时进行本地提交commit 当我们完成一个完整模块的开发后会将本地新分支的代码合并到开发分支 最后提交push到远程仓库前先进行拉取pull如果有冲突就先进行冲突解决解决完毕之后再push 49.说几个常用的运维命令 查看目录 ls 查看简单信息 ll -a 查看所有详情 切换目录 cd /绝对路径 ./ …/相对路径 创建目录mkdir -pv 目录名 删除目录(文件)rm -rf 目录(文件) 复制目录(文件)cp -r 原位置 新位置 剪切目录(文件)mv 原位置 新位置 编辑文件 vim 文件名 命令模式 i 编辑模式 esc 命令模式 :wq 查看文件more 文件名 文件压缩tar -zcvf xxx.tar.gz 指定文件 文件解压tar -zxvf xxx.tar.gz -C /指定解压路径 文件授权chmod 755 -R 目录文件 防火墙 服务: systemctl start|stop|status|restart firewalld 策略: 开启: firewall-cmd --zonepublic -add-port80/tcp --permanent 关闭: firewall-cmd --zonepublic -remove-port80/tcp --permanent 重载: firewall-cmd --reload 查看: firewall-cmd --zonepublic --list-ports 查看端口(8080)netstat -an | grep 8080 查看进程(tomcat)ps -ef | grep tomcat 强杀进程kill -9 pid 50.说几个常见的vue指令 双向绑定(v-model)用于实现双向数据绑定。它将表单元素的值与 Vue 实例的数据进行关联使得数据的改变会自动反映在表单元素上同时用户的输入也会更新数据。 属性绑定(v-bind)用于绑定 HTML 元素的属性或组件的属性。可以动态地将数据绑定到元素的属性上使其可以根据数据的变化而变化。 列表遍历(v-for)用于循环渲染列表数据。通过遍历数组或对象可以生成重复的 HTML 元素并绑定相应的数据。 条件判断(v-if/v-show) v-if根据表达式的真假条件来决定是否渲染 DOM 元素。如果条件为真则渲染元素如果条件为假则从DOM中移除元素。 v-show根据表达式的真假条件来控制元素的显示和隐藏。如果条件为真则显示元素如果条件为假则隐藏元素但不会从DOM中移除。 事件绑定(v-on)用于监听 DOM 事件并触发相应的方法。可以在 HTML 元素上绑定事件监听器比如点击、输入等事件。 异步交互(axios) 51.项目处理过哪些问题让你记忆深刻如何解决的 52.公司有多少人有多少开发人员有多少前端人员有多少产品经理 项目经理1人对整个项目负责任务分配、把控进度 产品经理1人进行需求调研输出需求调研文档、产品原型等 UI设计师1人根据产品原型输出界面效果图 架构师0人项目整体架构设计、技术选型等 开发工程师32功能代码实现 测试工程师2人编写测试用例输出测试报告 运维工程师1人软件环境搭建、项目上线 53.公司在哪个城市那个大厦那条街你住在哪里怎么去公司 54.项目中遇到的异常有哪些怎么解决这些异常 55.为什么离职 56.上家薪资构成社保基数 57.现在有offer了吗为什么没有去 58.加班怎么看
http://www.pierceye.com/news/694598/

相关文章:

  • 重庆市建筑工程信息官方网站注册号域名后如何建设公司网站
  • 江门网站建设junke100深圳小企业网站建设设计制作
  • 个人域名能做网站吗江苏外贸型网站制作
  • 文登区做网站的公司琴行网站开发学术论文
  • 嵌入式网站开发学习百度seo优化收费标准
  • 网站评价及优化分析报告湖南省邵阳建设局网站
  • 网站推广是做什么的深圳市住房建设与保障局官方网站
  • qq群推广网站lamp网站开发制作
  • ui网站界面设计广州省建设监理协会网站
  • 网站界面设计教程宁波正规网站seo公司
  • 网站建设与管理中专上海注册公司注册地址
  • 清溪网站建设怎么用wordpress打开网站
  • 网站稳定性不好的原因wordpress仿站维护
  • 银行管理系统网站建设最专业的医疗网站建设
  • 网站应该怎么做住建官网查询
  • 建设网站类型条形码生成器在线制作图片
  • 邯郸广告公司网站建设seo排名怎么做
  • 大眼睛网站建设做艺术品的网站
  • 自助免费网站建设平台网站开发php还是jsp
  • 网站建设成本多少北京怎么进行网页设计
  • 给个网站做导航违法吗游戏推广员每天做什么
  • 交互式网站开发技术全国企业信用公示信息公示网官网
  • 大连网站设计公司排名班级优化大师的功能有哪些
  • 旅游网站建设的概念ppt模板自己制作
  • 重庆网站建设首选承越网站开发建设方案
  • 创建一个网站的费用网站服务器租用报价
  • 潍坊企化网站建设大型免费网站制作
  • 松原网站制作网页制作的基本步骤流程
  • 太原网站建设制作机构西安网络seo公司
  • 移动网站建设报价表抖音代运营商