1.Debug.WriteLine、Trace.WriteLine
//WriteLine Write Print
Debug.WriteLine("debug调试模式下--在跟踪窗口--输出指定内容:",message);
//Trace.Write
Trace.WriteLine("debug replease模式--在跟踪窗口--下输出指定内容", message);
Debug.write()用于调试模式下在输出窗口,输出调试信息
Trace.Write()则可在调试和replease模式下同时在输出窗口,输出调试信息
注:
Debug会产生pdb文件,release不会。
Debug用于开发时的调试,不能要于部署。
Release用于部署.debug编译一些特殊代码,比如#IFDEBUG Debug.Write等,而Release则会将那些特殊标记省略
2.params:https://learn.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2010/w5zay9db(v=vs.100)
params 关键字可以指定采用数目可变的参数的方法参数。
可以发送参数声明中所指定类型的逗号分隔的参数列表或指定类型的参数数组。 还可以不发送参数。
在方法声明中的 params 关键字之后不允许任何其他参数(该参数必须是最后一个参数),并且在方法声明中只允许一个 params 关键字。
1 public class MyClass 2 { 3 public static void UseParams(params int[] list) 4 { 5 for (int i = 0; i < list.Length; i++) 6 { 7 Console.Write(list[i] + " "); 8 } 9 Console.WriteLine(); 10 } 11 12 public static void UseParams2(params object[] list) 13 { 14 for (int i = 0; i < list.Length; i++) 15 { 16 Console.Write(list[i] + " "); 17 } 18 Console.WriteLine(); 19 } 20 21 static void Main() 22 { 23 // You can send a comma-separated list of arguments of the 24 // specified type. 25 UseParams(1, 2, 3, 4); 26 UseParams2(1, 'a', "test"); 27 28 // A params parameter accepts zero or more arguments. 29 // The following calling statement displays only a blank line. 30 UseParams2(); 31 32 // An array argument can be passed, as long as the array 33 // type matches the parameter type of the method being called. 34 int[] myIntArray = { 5, 6, 7, 8, 9 }; 35 UseParams(myIntArray); 36 37 object[] myObjArray = { 2, 'b', "test", "again" }; 38 UseParams2(myObjArray); 39 40 // The following call causes a compiler error because the object 41 // array cannot be converted into an integer array. 42 //UseParams(myObjArray); 43 44 // The following call does not cause an error, but the entire 45 // integer array becomes the first element of the params array. 46 UseParams2(myIntArray); 47 } 48 } 49 /* 50 Output: 51 1 2 3 4 52 1 a test 53 54 5 6 7 8 9 55 2 b test again 56 System.Int32[] 57 */View Code
3.delegate是引用类型还是值类型?enum、int[]和string呢(难度系数40%)?
答案:delegate引用类型,enum值类型,int[]引用类型,string引用类型。
虚方法==》虚方法的使用,一般应用于面向对象的多态场景。
使用vitural关键字;
虚方法的定义可以有方法体,其派生类可以重新虚方法,也可以不重写,重写使用override
抽象类abstract
抽象类中不一定有抽象方法
有抽象方法的一定是抽象类
抽象类用于声明抽象方法,可以有属性,但不能有构造,不能使用new实例化
抽象类的派生类必须重写抽象类的抽象方法
接口interface:一般定义采用I开头
用于方法的声明,不能有方法体,不能有修饰符
全部的方法都是抽象的,一个类可以继承多个接口;
继承接口的类,必须实现定义的所有方法
密封类sealed
密封类不能被继承
重写与重载
重写是两个之间的关系,是子类和父类之间方法的重写关系
重载是一个类内的内部关系,即方法名称相同,参数个数或参数类型不同
数组没有Length()方法,有length属性
Array数组使用sort()排序;
ArrayList使用orderby\thenby\orderbydesc...排序
引用类型+值类型
装箱== 值类型到引用类型
拆卸==引用类型到值类型
常见值类型:常用普通数据类型,例如:int、double、char、bool、long、short、结构、枚举...
常见引用类型:string、object、类、接口
类、结构==》类为引用类型;结构为值类型;
类可以有构造,默认有无参构造;可通过new实例化——结构不能有构造,不能new
try catch finally ,finally在 return 后执行
MVVM--Model-view-viewmodel。
其本质就是MVC 模型、视图、控制器的改进版本
常用的如prism
在wpf应用中相关的一些技术或方法如,路由事件绑定、通知项属性、命令、通过dataContext上下文使模型、视图、控制器建立联系。
Using语句的作用==》
- 导入命名空间
- 类型别名
- try finally语法糖,避免手动释放dispose释放资源
第一问:C#中变量类型分为哪两种?
值类型和引用类型,值类型变量自身存储数据,引用类型存储的是实际数据的引用,通过引用找到实际的数据。
第二问:Class和Struct的区别?
Class为引用类型,可以被new实例化,默认private,存储实际的引用;
Struct为值类型,不能new示例,默认public,值类型自身存储数据数据。
第三问:C#中类的修饰符和类成员的修饰符有哪些?
C#中可以修饰类的修饰符为:public、internal、sealed、abstract
C#中不能修饰类的修饰符为:private和protected
C#中成员的修饰符为:public、internal、protected、private
public:完全公开,没有访问限制。
internal:可以应用于当前应用程序以及类库。
protected:在当前类和子类中可以使用。
private:只有在当前类中可以使用。
sealed:密封类,不能被其他类型继承。
abstract:抽象类,不能创建实例。
第四问:面向对象的三个特征(特点)是什么?
封装:把对象的属性或者行为封装起来,类似于一个类。
继承:子类可以继承父类。
多态:父类可以应用于子类,子类可以去使用父类的一些特征方法。
第五问:面向对象和面向过程的区别?
面向对象:把问题分解成多个对象,强调的是解决问题行为标准(方式)
面向过程:分析问题并解决问题的步骤,强调的是解决问题的步骤。
第六问:什么是装箱和拆箱?
装箱:从值类型转换到引用类型。
拆箱:从引用类型到值类型的转换。
第七问:什么事IOC?
控制反转,是一种思想(设计模式)而不是一种技术实现。
控制:拥有创建对象的权利。
反转:把控制权交给IOC容器。
优点: 1、对象之间的耦合度或依赖度降低。
2、资源容易管理
传统模式下:在一个类中需要new关键字去实例化另一个类。
IOC设计模式:不需要new去创建对象,直接从IOC容器中获取。
第八问:什么事OOP?
面向对象编程
提取共有的属性和方法,形成一个父类。
第九问:什么事AOP?
面向切面的编程,在不改变原有的业务逻辑情况下,横切逻辑代码,解耦合代码,避免横切代码重复。
切:指的是横向逻辑,就是保证原有的业务逻辑代码不变,操作横切逻辑代码,所以就是面相横切编程。
面:横切代码影响的是很多方法,每个方法如同一个点,很多点就形成面。
应用场景:事务控制,权限效验、日志信息等。
多个方法的相同位置出现重复代码。
第十问:什么事DI?
依赖注入:构造注入、方法注入、属性注入
DI是IOC设计思想的实现方式
一个类去引用另外一个类,就会产生依赖。
优点:如果添加另一个类,不需要修改之前代码,只要修改注入的地方将实现类进行替换。实例化接口的时候,不用手动new来狗仔实现类,交给IOC容器进行构建。
实现了解耦
DIP:依赖注入倒置原则:依赖于抽象,不依赖预聚体,高层模块不依赖于低层模块,它们依赖于抽象。
代码中如何实现多态
接口实现 继承父类重写方法 同一类中进行方法重载
描述sealed修饰符的使用
sealed修饰符用于修饰类、实例方法和属性。sealed用于修饰类时,该类无法被继承,所以该类也被称为密封类。而abstract类(抽象类)必须被继承才有意义,所以,sealed修饰符和abstract修饰符是互相排斥的,无法共存。密封方法会重写基类的方法,sealed用于修饰实例被重写的虚方法或虚属性时,表示该方法或属性无法再被重写。
IOC/DI/AOP
1.IOC即控制反转,是一种设计思想,在之前的项目中,当我们需要一个对象时,需要new一个对象,而IOC的设计思想是我们将需要的对象注入到一个容器中,就会获得我们所需要的资源 。
2.DI是依赖注入,我们将需要的对象注入到容器中,获取所需要的资源。
3.AOP 在运行时,动态地将代码切入到指定方法、指定位置上的编程思想就是面向切面的编程。
使用:先创建一个类继承自IAsyncActionFilter、在startup中添加 依赖、然后添加标签
进程和线程的关系:
1.一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
2.资源分配给进程,同一进程的所有线程共享该进程的所有资源。
3.线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
线程与进程的区别:
1.调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。
2.并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。
3.拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。
类和结构的区别?
结构和类具有大体的语法,但是结构受到的限制比类要多。结构不能申明有默认的构造函数,为结构的副本是又编译器创建和销毁的,所以不需要默认的构造函数和析构函数。结构是值类型,所以对结构变量所做的改变不会影响其的原值,而类是引用类型,改变其变量的值会改变其原值。申明结构用Struck 关键字,申明类用 class 关键字,向方法传递结构是时是通过值传递的,而不是通过引用。与类不同,结构的实例化可以不使用New关键字。类可以实现接口。
值类型和引用类型的区别?
值类型是存放在栈中的,改变其值,不改变变量原有的值,而引用类型的值是存放在堆中的,其引用的地址是存放在栈中的,改变其值也就改变了变量原有的值。值类型不允许包含null值,然而可空类型可以将null赋值给值类型l。
foreach 和 for 循环从性能角度的区别。
对于for循环就是调用get(i)取得元素,而对于foreach是通过iterator实现的遍历,
对于数组来说,for和foreach循环效率差不多,但是对于链表来说,for循环效率明显比foreach低。
抽象方法和虚方法的区别
抽象方法一定是虚方法,虚方法未必是抽象方法。虚方法是指可以被继承类重写的方法,而抽象方法是指,基类是抽象类,没有实现它,因此必须被继承类重写的方法。
抽象与接口:
构造器Constructor是否可以被继承?是否可以被Override?
Constructor不可以被继承,因此不能被重写(Overriding),但可以被重载(Overloading).
Const和ReadOnly?
Const用来申明编程时申明常量,是静态常量,不可被static修饰,ReadOnly用来申明运行时常量,是动态常量,使用时才会初始化。
HTTP状态码:
200:请求被正常处理
400:请求报文语法有误,服务器无法识别
403:请求的对应资源禁止被访问
404:服务器无法找到对应资源
500:服务器内部错误000
503:服务器正忙
.Net Core 3.0和2.0 相比,加了哪些东西, net5?
只保留了一些必要的包,去除了其他(如EF,JSON.NET),删除很多过时的API,授权有了很大改变,SigfnalR修改,MVC,Rezor修改。
.Net 5 Framework,Core核心的结合,blaze,socket, .Net Xamarin 趋于统一
.net core和.net framework的区别
- 跨平台,它可以运行在三大操作系统上面,windows, Linux和MAC。
- 对架构本身安装没有依赖,因为所有的依赖都跟程序本身在一起。
- 更高的性能和处理能力,支持docker
- 内置依赖注入,日志处理
- 还有HTTP请求管道
Singleton
单例模式,服务在第一次请求时被创建,其后的每次请求都沿用这个已创建的服务。我们不用再自己写单例了。
Scoped
作用域模式,服务在每次请求时被创建,整个请求过程中都贯穿使用这个创建的服务。比如Web页面的一次请求。
Transient
瞬态模式,服务在每次请求时被创建,它最好被用于轻量级无状态服务。
如果一个系统出现性能瓶颈,让你来处理的话,说说你的性能优化计划。
硬件上,加服务器配置,固态内存等,多台服务器集群负载均衡,或者业务拆分(分布式)。
设计上,可以使用读写分离、分库分表、Redis、Elasticsearch、MQ排队
代码上,简化代码、冗余字段、文件压缩、图片压缩、前端体验(loading动画、伪进度条)。
集群、分布式和微服务的区别
分布式:一个业务拆分成多个子业务,子业务分别部署在不同的服务器上。
集群:同一个业务,部署在多个服务器上。
微服务:就是很小的服务,小到一个功能就是一个服务,可以单独部署运行。
微服务和分布式之间的区别就是微服务的应用不一定分散在不同的服务器上,也可以在同一个服务器上多个服务。
分布式系统解决数据一致性问题
CAP 是指在一个分布式系统下, 包含三个要素:Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),并且三者不可得兼。
2PC(两阶段提交)、3PC(三阶段提交): 省略
TCC方案:
每一次事务都要定义三个操作,try-confirm-cancel。而且TCC对业务的侵入性比较大,每个业务都要写相应得到撤销方法。
最大努力通知:
其实也算是一种最终一致性的方案,主要是当A系统执行完本地事务后,发送消息给MQ,然后去让B系统执行事务操作,如果B系统执行完成了,就消费消息,若B系统执行失败了,则执行重试,重试多次直到成功。若达到一定次数后还没成功就只能人工干预了。
C#中的委托是什么?事件是不是一种委托?
委托的本质是一个密封类。这个类继承自System.MultiDelegate,其再继承自System.Delegate。这个密封类包括三个核心函数,Invoke方法赋予其同步访问的能力,BeginInvoke,EndInvoke赋予其异步访问的能力。委托他可以把一个方法作为参数代入另一个方法,委托可以理解为指向一个函数的引用。
事件是一种特殊的委托,是委托的一个实例,事件的内部是用委托实现的,事件内部就是一个private的委托和add、remove两个方法
delegate <函数返回类型> <委托名> (<函数参数>)
为什么要使用委托?
逻辑解耦,保持程序稳定,代码复用,保证项目的规范性。
怎么使用事件?
声明委托 声明事件 事件注册
为什么要使用扩展方法?
和抽象类比较,需要扩展密封类的方法时,我们可以使用到扩展方法。在扩展接口的时候。需要扩展,要继承实现接口(会强制要求实现接口下的所有方法)。
简述 private、 protected、 public、internal 修饰符的访问权限。
private : 私有成员, 在类的内部才可以访问。 类成员默认
protected: 保护成员,该类内部和继承类中可以访问。
public: 公共成员,完全公开,没有访问限制。
internal:在同一命名空间内可以访问。 类默认
internal protected:在所属程序集或当前类的子类中可以访问。
描述类和对象的区别
类(即class)指一类事物,对象(即object)指属于这一类事物的实体。类定义了对象的相关数据和方法,类通过构造函数生成对象,对象实现了类的定义,且拥有具体的数据。
代码中如何实现多态
接口实现 继承父类重写方法 同一类中进行方法重载
描述sealed修饰符的使用
sealed修饰符用于修饰类、实例方法和属性。sealed用于修饰类时,该类无法被继承,所以该类也被称为密封类。而abstract类(抽象类)必须被继承才有意义,所以,sealed修饰符和abstract修饰符是互相排斥的,无法共存。密封方法会重写基类的方法,sealed用于修饰实例被重写的虚方法或虚属性时,表示该方法或属性无法再被重写。
IOC/DI/AOP
1.IOC即控制反转,是一种设计思想,在之前的项目中,当我们需要一个对象时,需要new一个对象,而IOC的设计思想是我们将需要的对象注入到一个容器中,就会获得我们所需要的资源 。
2.DI是依赖注入,我们将需要的对象注入到容器中,获取所需要的资源。
3.AOP 在运行时,动态地将代码切入到指定方法、指定位置上的编程思想就是面向切面的编程。
使用:先创建一个类继承自IAsyncActionFilter、在startup中添加 依赖、然后添加标签
C#类成员一般初始化顺序:
子类静态字段\子类静态构造\子类实例字段\父类静态字段\父类静态构造\父类实例字段\父类实例构造\子类实例构造
进程和线程的关系:
1.一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。
2.资源分配给进程,同一进程的所有线程共享该进程的所有资源。
3.线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。
线程与进程的区别:
1.调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位。
2.并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可以并发执行。
3.拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源。
类和结构的区别?
结构和类具有大体的语法,但是结构受到的限制比类要多。结构不能申明有默认的构造函数,为结构的副本是又编译器创建和销毁的,所以不需要默认的构造函数和析构函数。结构是值类型,所以对结构变量所做的改变不会影响其的原值,而类是引用类型,改变其变量的值会改变其原值。申明结构用Struck 关键字,申明类用 class 关键字,向方法传递结构是时是通过值传递的,而不是通过引用。与类不同,结构的实例化可以不使用New关键字。类可以实现接口。
值类型和引用类型的区别?
值类型是存放在栈中的,改变其值,不改变变量原有的值,而引用类型的值是存放在堆中的,其引用的地址是存放在栈中的,改变其值也就改变了变量原有的值。值类型不允许包含null值,然而可空类型可以将null赋值给值类型l。
foreach 和 for 循环从性能角度的区别。
对于for循环就是调用get(i)取得元素,而对于foreach是通过iterator实现的遍历,
对于数组来说,for和foreach循环效率差不多,但是对于链表来说,for循环效率明显比foreach低。
C# IQueryable和IEnumerable的区别
在Queryable中,参数接收的是一个表达式类型Expression,返回IQueryable接口
在Enumerable中,参数接收的是一个谓词表达式Func<>,也就是一个委托
IEnumerable<T> 泛型类在调用自己的SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了,而IQueryable<T> 是将Skip ,take 这些方法表达式翻译成T-SQL语句之后再向SQL服务器发送命令,它并不是把所有数据都加载到内存里来才进行条件过滤。
抽象方法和虚方法的区别
抽象方法一定是虚方法,虚方法未必是抽象方法。虚方法是指可以被继承类重写的方法,而抽象方法是指,基类是抽象类,没有实现它,因此必须被继承类重写的方法。
为什么要是使用抽象?为什么要使用接口?
先用接口确定系统行为,然后用Mock类进行对接口的实现,在这个时候根本就没抽象类什么事情。接口表达一个契约,表达系统和系统间的协议,属于业务层。
很多具体类,出现很多重复代码,将其提炼出抽象类简化代码。而抽象类不过是提取公因式,简化代码而已。
构造器Constructor是否可以被继承?是否可以被Override?
Constructor不可以被继承,因此不能被重写(Overriding),但可以被重载(Overloading).
Const和ReadOnly?
Const用来申明编程时申明常量,是静态常量,不可被static修饰,ReadOnly用来申明运行时常量,是动态常量,使用时才会初始化。
数据库与缓存
索引原理及使用
底层是经过优化的B+树,索引在频繁查询的、需要排序的字段上使用。索引需要占用物理空间,当对表进行增、删、改、的时候索引也要动态维护,这样就降低了数据的维护速度。
创建索引:CREATE INDEX index_name ON table_name (column_name) ;
什么情况下设置了索引但无法使用
以“%”开头的LIKE语句,模糊匹配,OR语句前后使用索引
简单描述mysql中,索引,主键,唯一索引,联合索引的区别,对数据库的性能有什么影响(从读写两方面)
普通索引(由关键字KEY或INDEX定义的索引)的唯一任务是加快对数据的访问速度。
普通索引允许被索引的数据列包含重复的值。如果能确定某个数据列将只包含彼此各不相同的值,在为这个数据列创建索引的时候就应该用关键字UNIQUE把它定义为一个唯一索引。也就是说, 唯一索引可以保证数据记录的唯一性。
主键,是一种特殊的唯一索引,在一张表中只能定义一个主键索引,主键用于唯一标识一条记录,使用关键字PRIMARY KEY 来创建。
索引可以覆盖多个数据列,如像INDEX(columnA, columnB)索引,这就是联合索引。
索引可以极大的提高数据的查询速度,但是会降低插入、删除、更新表的速度,因为在执行这些写操作时,还要操作索引文件。
聚集索引与非聚集索引的区别
聚集索引一个表只能有一个,key值应该是唯一的,而非聚集索引一个表可以存在多个
聚集索引存储记录是物理上连续存在,而非聚集索引是逻辑上的连续,物理存储并不连续
谈谈数据库分库分表的方式。
1.垂直切分:
根据业务的不同,将原先拥有很多字段的表拆分为两个或者多个表,这样的代价我个人觉得很大,原来对这应这个表的关系,开始细分,需要一定的重构,而且随着数据量的增多,极有可能还要增加水平切分;
2.水平切分:
数据库/数据表结构相同,将数据分散在多个数据库/表中;
3.取模分库:
一般的取模分库分表是就是将id mod n,然后放入数据库中,这样能够使数据分散,不会有热点的问题,那么,剩下的是,在扩容的时候,是否会有数据迁移的问题,一般的扩容,当然是会有数据迁移的。
预防死锁:
资源一次性分配:一次性分配所有资源,这样就不会再有请求了:(破坏请求条件)
只要有一个资源得不到分配,也不给这个进程分配其他的资源:(破坏请保持条件)
可剥夺资源:即当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源(破坏不可剥夺条件)
资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)
少用大事务,拆分小事务
数据库查询优化
- 加合理的索引,注意where后面的字段顺序,不允许null,%不能在左边。
- 读写分离,log同步。
- 拆分复杂的查询语句,少用子查询。
- Redis、elasticsearch
- 太复杂,quartz或者存储过程定时查询,查询结果放在结果表中,直接拿结果表的数据
- 冗余字段、
- 加内存加硬件
如何解决Redis缓存与MySQL的数据一致性问题
- 延时双删,先删缓存,再写数据库,休眠一段时间后,再删缓存。
- 异步消息梳理,读redis=>写mysql=>更新redis=>mq=>redis服务器订阅更新数据,然后同步更新
数据库中的隔离级别
脏读:是指一个事务读取了未提交事务执行过程中的数据。
不可重复读:A事务中第一次和第二次读取到的数据不一致,在A事务两次读取数据之间,B事务对数据进行了修改并且提交了,然后A事务第二次读取到的数据就是B事务修改之后的数据,导致A事务第一次和第二次读取到的数据不一致,这就叫做不可重复读。
幻读:它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
脏读 |
不可重复读 |
幻读 |
|
Read uncommitted |
√ |
√ |
√ |
Read committed--Sql Server , Oracle |
× |
√ |
√ |
Repeatable read--MySQL |
× |
× |
√ |
Serializable |
× |
× |
× |
事务特点;原子性、一致性、隔离性、持久性。
Redis
Redis 支持持久化,所以 Redis 不仅仅可以用作缓存,也可以用作 NoSQL 数据库。
相比 MC,Redis支持多种数据格式,例如 list、set、sorted set、hash 等,还有Incr decr自增自减、expire过期时间等功能。
Redis 提供主从同步机制,以及 Cluster 集群部署能力,能够提供高可用服务。
持久化:RDB 是把内存中的数据集以快照形式每隔一段时间写入磁盘,AOF 是以文本日志的形式记录 Redis 处理的每一个写入或删除操作。
缓存穿透
用户频繁请求不存在的数据接口,缓存里找不到,这时会有大量请求穿透缓存访问到 DB。
使用BloomFilter过滤器,BloomFilter 的特点是存在性检测,如果 BloomFilter 中不存在,那么数据一定不存在;如果 BloomFilter 中存在,实际数据也有可能会不存在。
缓存击穿
缓存击穿,就是某个热点数据失效时,大量针对这个数据的请求会穿透到数据源。
可以使用互斥锁更新
设置热点数据永远不过期。
缓存雪崩
缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。
缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。
设置热点数据永远不过期。
框架与设计
.Net Core 3.0和2.0 相比,加了哪些东西, net5?
只保留了一些必要的包,去除了其他(如EF,JSON.NET),删除很多过时的API,授权有了很大改变,SigfnalR修改,MVC,Rezor修改。
.Net 5 Framework,Core核心的结合,blaze,socket, .Net Xamarin 趋于统一
.net core和.net framework的区别
- 跨平台,它可以运行在三大操作系统上面,windows, Linux和MAC。
- 对架构本身安装没有依赖,因为所有的依赖都跟程序本身在一起。
- 更高的性能和处理能力,支持docker
- 内置依赖注入,日志处理
- 还有HTTP请求管道
Singleton
单例模式,服务在第一次请求时被创建,其后的每次请求都沿用这个已创建的服务。我们不用再自己写单例了。
Scoped
作用域模式,服务在每次请求时被创建,整个请求过程中都贯穿使用这个创建的服务。比如Web页面的一次请求。
Transient
瞬态模式,服务在每次请求时被创建,它最好被用于轻量级无状态服务。
如果一个系统出现性能瓶颈,让你来处理的话,说说你的性能优化计划。
硬件上,加服务器配置,固态内存等,多台服务器集群负载均衡,或者业务拆分(分布式)。
设计上,可以使用读写分离、分库分表、Redis、Elasticsearch、MQ排队
代码上,简化代码、冗余字段、文件压缩、图片压缩、前端体验(loading动画、伪进度条)。
集群、分布式和微服务的区别
分布式:一个业务拆分成多个子业务,子业务分别部署在不同的服务器上。
集群:同一个业务,部署在多个服务器上。
微服务:就是很小的服务,小到一个功能就是一个服务,可以单独部署运行。
微服务和分布式之间的区别就是微服务的应用不一定分散在不同的服务器上,也可以在同一个服务器上多个服务。
分布式系统解决数据一致性问题
CAP 是指在一个分布式系统下, 包含三个要素:Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),并且三者不可得兼。
2PC(两阶段提交)、3PC(三阶段提交): 省略
TCC方案:
每一次事务都要定义三个操作,try-confirm-cancel。而且TCC对业务的侵入性比较大,每个业务都要写相应得到撤销方法。
最大努力通知:
其实也算是一种最终一致性的方案,主要是当A系统执行完本地事务后,发送消息给MQ,然后去让B系统执行事务操作,如果B系统执行完成了,就消费消息,若B系统执行失败了,则执行重试,重试多次直到成功。若达到一定次数后还没成功就只能人工干预了。
标签:C#,可以,笔记,索引,线程,引用,类型,方法 From: https://www.cnblogs.com/YYkun/p/18140929