周五问题总结

问题1 操作系统是如何实现进程,线程的, 一般而言,我们的电脑是2核4线程的,和这个有关系吗?

解答:进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,
在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,
但线程之间没有单独的地址空间,一个线程死掉就等于整个线程死掉,所以多进程的程序要比多线程的程序健壮,
但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,
只能用线程,不能用进程。

问题2 锁是如何实现的,是在需要锁定参数上添加属性吗,当多线程时,如果一条线程获得锁,其他线程是处于阻塞状态吗,当释放锁的时候,其他线程如何知道锁已释放

解答:锁基本为内核层面完成,当一条线程获得锁后,操作系统将数据添加属性,其他线程无法获得,线程操作结束后,操作系统会唤醒其他线程,继续对数据进行访问

问题3 REDIS持久化是操作系统实现的吗,REIS持久化时运用COW原理,其中提到 REDIS的数据段是由很多操作系统的页面组合而成, 其中操作系统的页面是什么

解答: redis持久化是由redis进程实现。
      redis运用cow(写时复制原理)原理,主要是运用在redis持久化过程中,其中快照功能运用到:在持久化时,redis会将内容全部内容复制到磁盘中,父进程生成子进程,为节省资源,父子进程指向同一片内存,这时为了保证用户的可用性,当内容修改时,子进程将资源复制出一份处理修改内容,父进程继续进行持久化进程。

操作系统页面:
        1、为了进程的便利性和安全性,操作系统形成了虚拟内容的概念,进程操作虚拟内存,操作系统将虚拟内存与物理内存建立关系。
        2、既然氛围虚拟和物理内存,那就需要有关系表,但是如果,一一对应,那关系表将非常大,浪费空间,查找对应关系也会很麻烦,所以建立了分页的概念。
        3、分页后,每页的大小为4kb,即4096个字节,只需要将页数进行对应即可,这要所需空间就变为4096分之一,操作系统只需要记住页数和偏移量,就可以找到物理地址。

关于操作系统页面分享一篇博客:[3]: https://www.cnblogs.com/vamei/p/9329278.html

问题4 MYSQL中建立索引可以提高查询速度,索引的原理是什么,建立索引以后对这个字段做了什么操作?

解答:首先索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表进行全表扫描,直到找出相关的行,才会停止.表越大,查询数据所花费的时间就越多,如果表中查询的列有一个索引,
MySQL能够快速到达一个位置去搜索数据,而不必查看所有数据,那么将会节省很大一部分时间,提高数据查询速度,从而提高性能.我们知道从数据库中读取数据都是进行的IO操作,所以查询效率都是取决于IO操作的次数,
只要减少IO操作就可以提高查询效率,然而索引正是基于了磁盘IO预读机制的,数据库是InnoDB引擎,一般是使用B+Tree的索引数据结构,B+Tree是在B-Tree上进行优化的,通过在原B-Tree的各个节点数据的重复元素索引,
将树的形状构建成”矮胖“型也减少了Tree的层级,原本查询需要一层一层的往下查询,所以Tree的层级数就决定了IO操作的次数,所以也就提高的查询速度,各个叶节点的数据只做为索引,不作为数据返回,
只在最后一个层级返回相对应的数据.一般B+Tree的索引结构数据一般在三个层级.大大提高了查询效率.

推荐书籍 <<高性能MySQL>> 可以了解mysql原理,这本书讲的比较深入

问题5 DJANGO集成的日志系统,怎么监控输出的?

解答:首先Django中使用的日志模块也是python中的日志模块.日志是对程序运行的的跟踪和监控将执行程序的一些信息进行记录,便于在出现问题时准确定位.而在python中的有logging这个标准模块,
它集成了一些处理日志的组件和函数,根据不同的日志等级区别输出类型,其中组件有日志器(Logger),处理器(Handler),过滤 
器(Filter)和格式器(Formatter),其中Logger在使用接口debug,info,warn,error,critical之前会创建Logger实例,即创建 
一个记录器,如果没有创建,则默认会创建一个root logger,并应用默认的日志级别(WARN),
处理器Handler(StreamHandler,即将日志信息打印输出在标准输出上),和格式化器Formatter(默认的格式即为第一个简单使用程序中输出的格式).
Handler是根据执行程序的日志,创建出logger然后将生成的日志发送到适合的目的输出.
Filter就是在程序执行过程中会生成许多执行信息,然后将这些信息通过对logging的配置进行过滤,筛选决定哪些日志信息需要记录下来.Formatter是根据开发者定义的日志格式将日志格式化的输出.
几个组件配置工作从日志生成到输出.
还有根据不同日志等级创建不同日志记录的函数Logger.debug()/info()/warning()/ error()/critical().通过开发者在配置中的logging.basicConfig()实现不同日志等级的输出.

关于django日志系统分享一篇博客:[3]: https://blog.csdn.net/qq_33339479/article/details/85044966

问题6 PYTHON的第三方库GEVENT的运作原理是怎样的呢?

解答:gevent是第三方库,通过greenlet实现协程,对greenlet做了扩展,其基本思想是:
当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。
由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO.

关于gevent分享一篇博客:[3]: https://blog.csdn.net/qq_33339479/article/details/81143775

问题7 协程中YIELD FROM的机制是怎样的?

解答:yield from 语法,允许一个generator生成器将其部分操作委派给另一个生成器.Python的生成器是协程coroutine的一种形式.
yield from允许子生成器直接从调用者接收其发送的信息或者抛出调用时遇到的异常,并且返回给委派生成器一个值. 

使用send()方法发给委派生产器(即外部生产器)的值被直接传递给迭代器。如果send值是None,则调用迭代器next()方法;如果不为None,则调用迭代器的send()方法。
如果对迭代器的调用产生StopIteration异常,委派生产器恢复继续执行yield from后面的语句;若迭代器产生其他任何异常,则都传递给委派生产器.

关于协程分享一篇博客:[3]:  https://blog.csdn.net/qq_33339479/article/details/78597949
                        https://blog.csdn.net/u010161379/article/details/51645264

问题8 在自定义可迭代对象的时候,不能同时实现__ITER__方法和__NEXT__方法

解答:因为根据迭代器模式要求,同一个可迭代对象中必须能够获取多个迭代器,如果在可迭代对象类实现以上两种方法并让__iter__方法返回self本身,
会导致一个可迭代对象实例中只能获取到一个迭代器,从而让同一个可迭代对象无法进行多种遍历。

问题9 TRY...EXCEPT…语句在做流程控制之用的时候,和IF…ELSE…语句的流程控制有什么区别?

解答:在代码中大量使用 try...except...语句和在代码中大量使用 if...else...语句是两种不同的编码风格。try 语句是先假定目标代码能够运行,如果假定不成立,那么运行其他代码 ;
if 语句是在运行目标代码前测试前提条件,成立则运行目标代码,不成立则运行其他代码。
他们的区别是try语句比if语句少了条件测试环节,因而相对来说,try语句更简单明快,使用这种风格的时候要结合else和fanaly语句。
并且在多线程环境中,因为try语句没有 条件测试 和 目标代码运行 之间的空档,从而可以避免因空档期引起的条件竞争。

问题10 使用生成器函数处理超多文件数据的时候,可以用多个生成器形成数据处理管道,这多个生成器之间是怎样运行的?

解答:使用多个生成器组成的数据处理管道可以处理流程复杂的数据,比如多文件目录。这种方法每个生成器小并且独立,而且节约内存。
上一个生成器生成的数据是下一个生成器的参数,如此形成一组数据流流向遍历语句块或驱动函数。
如多文件目录处理流程:获取完整的文件名——>解压缩文件——>获取文件中的每一行的数据——>正则匹配获取目标数据——遍历驱动数据管道。

问题11 DJANGO中MOCK的使用:

解答:关于写测试用例时候用到的mock方法
如果系统中有很多外部依赖,我们不需要也不希望把所有的部件都运行一遍,我们只需要知道代码按照预期执行,并调用了相关的外部接口
所以,mock是替换代码中外部的服务,因为python是动态语言,一切都是对象,所以在执行之前把实例,方法,函数和变量替换掉。下面是实例
@mock.patch('mall.apis.sendsms')# sendsms是一个发送短信的service函数
def test_post1(self, mock_order, sendsms):
    sendsms.return_value = None # return_value表示我们自定义的这个函数的返回值,
    data = {'phone': '13255968961'}
    resp = self.client.post(self.url, data=data)
    self.assertEqual(resp.status_code, 200)

分享一篇博客 [3]: https://blog.csdn.net/qq_33339479/article/details/84578544

问题12 微信支付问题分享

微信JSAPI支付方式小坑:
第一点,公众账号配置的参数一定得正确,appid appsecret,appkey记得是商户号里面设置的key,还有商户号,
第二点,生成xml数据时一定得注意,不要根据他现在的文档格式生成,一定要加上CDATA这个防止转义的字符,要不然一直报错,
第三点,生成xml数据时一定得注意,一定要排序,一定要排序,根据字典的key值排序后再生成数据,血泪教训啊,
第四点,生成签名,JSAPI支付方式拿到前段传给我们的openID后,我们后台签名生成XML数据,访问微信后台,获取到prepay_id,然后会在
       重新签名,这个时候一定得注意,一定得注意,一定得注意,字典中参数的key值,是按驼峰命名的方式来的,首字母小写,第二个单词字母大写,跟之前的签名key值不一样
第五点,微信支付成功以后,微信后台会多次异步访问我们的notify_url,最好是拿到订单号后,先检索下这个订单状态是否是已支付状态,是的话就不做业务逻辑了
第六点,微信支付成功以后,微信后台会多次异步访问我们的notify_url,业务逻辑做完以后,一定要按他的要求返回一段XML数据,content_type='text/xml'
第七点,微信支付中支付金额有点反人类,他的最小单位是分,比如支付1毛钱,你需要传输10,比如你想支付0.012元,对不起,要么是四舍五入1或者进一法2
第八点,所有的参数都是字符串,所以支付金额要转为字符转格式。
第九点,微信退款时候,访问退款接口,需要传输配置证书,证书需要从微信商户号下载。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值