python就业班第34天----单元测试、Redis、集群

导包:会出来个_pycache_,里面放缓存,第一次运行程序跑的慢,第二次产生缓存之后执行代码速度会变快。缓存全是二进制文件(又叫字节码文件)


测试

web程序开发过程一般包括下面几个阶段:[需求分析、设计分析、实现阶段、测试阶段]

测试的分类:

  • 单元测试:对单独的代码块 ( 例如函数 ) 分别进行测试,以保证它们的正确性(由程序员完成)
  • 集成测试:对大量的程序单元协同工作情况做测试
  • 系统测试:同时对整个系统的正确性进行检查,而不是针对独立的片段

单元测试:经常使用的是断言 ( assert )
断言:和生活中到的语言,断定是一样的
格式:
assert boolean表达式 , 异常信息
例:如果num1是整数,测试通过,否则返回异常信息,显示"num1必须是整数类型"
assert isinstance(num1 , int) , "num1必须是整数类型"
isinstance:判断类型
格式:isinstance( 变量 , 数据类型)
如果变量是该数据类型,返回True,否则返回False

def divsion(num1,num2):
	assert isinstance(num1,int),"num1必须是整数类型"
	return num1/num2

print(divsion(10,5))
print(divsion("10",5))

python就业班第34天----单元测试、Redis、集群


搜索:

  • 1.搜当前文件 ctrl + f
  • 2.搜索整个项目 ctrl + shift + f
  • 3.搜索指定文件目录 ctrl + shift + f 找到scope的directory

python就业班第34天----单元测试、Redis、集群

python就业班第34天----单元测试、Redis、集群

python就业班第34天----单元测试、Redis、集群


测试:

  • 1.导入类unittest 的TestCase
    from unittest import TestCase
  • 2.编写自定义测试类,继承TestCase
    class DataBaseTest(TestCase):
  • 3.编写两个固定方法:setUp()和tearDown()
    setUp()测试执行前执行,tearDown()出错的时候执行

测试类可以直接运行(不用写__name__入口),右键,光标放到哪个测试业务方法右键运行,执行哪个测试方法
测试业务方法必须以test开头

千万不能在同一个数据库里做测试,必须要新建

案例:测试昨天的图书馆数据库

from unittest import TestCase
from demo02library import *

# 定义类,继承自TestCase
class DataBaseTest(TestCase):
	def setUp(self):
	# print("setUp")
	app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:[email protected]:3306/library16_test'
	db.create_all()

	def test_database_add_data(self):
		# 1.创建作者对象,添加到数据库中
		author = Author(name="banzhang")
		db.session.add(author)
		db.session.commit()

		# 2.查询出来
		author2 = Author.query.filter(Author.name=="banzhang").first()

		# 延时方法:
		import time
		time.sleep(10)

		# 3.断言了,作者对象一定不能为空,并且名字一定是班长
		self.assertIsNotNone(author2,"author2一定不能为空")
		self.assertEqual(author2.name,"name的值一定是班长")

	def tearDown(self):
		print("tearDown")

python就业班第34天----单元测试、Redis、集群

assertIsNotNone格式:必须写在测试类的方法里,不然找不到

from unittest import TestCase
class 类名(TestCase):
	def test后缀(self):
		self.assertIsNotNone(变量,"字符串")

assertIsNotNone:变量存在,则pass,不存在,测试时显示字符串
类似的还有很多,进去查看


Redis

Redis:非关系型数据库的一种
nosql介绍:一类新数据的数据库(not only sql)
泛指非关系型数据库
不支持sql语法
存储跟传统的完全不同,都是KV(keyvalue)形式,每种都有自己的api和语法,以及擅长的业务场景
nosql产品种类:MongoDB、Redis

NoSQL和SQL比较:
sql适用关系特别复杂的数据查询场景,nosql反之
sql支持事务,nosql不支持事务
虚读(幻读):看一个栏目,展开下滑到一半,去看另一个栏目,然后切回第一个栏目还能回到刚刚停留的位置


Redis简介:c语言编写,NoSQL阵营一员

Redis特效:数据存在内存(速度贼快),电脑关机时拍快照放硬盘,重启再次加载恢复;支持列表、集合、哈希等结构的存储,支持master-slave(哨兵模式)的集群

Redis安装和配置:另起文章说明
redis的logo:面包片

python就业班第34天----单元测试、Redis、集群


终端下:

查看帮助:redis-server --help
查看redis服务器进程:ps-aux|grep redis
杀死进程:kill -9 进程PID
sudo redis-server /etc/redis/redis.conf 加载指定的配置文件
启动服务端:redis-server

另开一个终端,进入客户端:redis-cli

查看redis服务器进程:ps-aux


客户端下:
运行测试,看是否能联通:ping
收到个PONG,表示连接OK

redis使用的数据库(类似mysql的use database)可以配置,默认是有16个,编号0-15,默认使用数据库0
切换到数据库10:select 10 返回个ok表示成功


增删改查:

string类型:

设置:set ; 获取:get
set name zhangsan 设置name为zhangsan
get name 获取name

设置存在一定的时间:setex
setex age 10 13 设置age为13,只存在10s

设置多个key和value:mset
mset name zhangsan sex man height 180
get sex

字符串追加:append
set name zhangsan
append name feng 给name追加个feng
get name 结果是zhangsanfeng
append haha 20 要是key没有,则自动生成

获取多个:mget
mget name sex height haha

查看:keys
keys * 查看全部
keys h* 查看h开头
keys *x 查看x结尾
keys *e* 查看包含e的

查看是否存在:exists
exists name 查看name是否存在,存在返回1,不存在返回0

查看类型:type
type name 查看name的类型

删除:del
del height haha 删掉height和haha,返回的是影响的结果数

删除所有:flushall
flushall 刷新所有,所有内容都清空

设置expire
expire name 10 给name设置10秒有效期
ttl name 查看name还有几秒到期,为负数就到期了

哈希类型:

redis操作hash类型
格式:hset key field value
filed:域的意思

看朋友圈滚滚滚,切出去,再切回来还能继续看
使用场景:分页缓存。跟哈希有关(类似字典、但又不一样。哈希key=>字典变量名,哈希field=>字典key)

hset person age 13
hset person name laowang
keys * 结果显示person只有一个
get person 报错,要用hget过去,而且hget person 也报错,后面要加filed
hget person name
hmset person name laowang age 18 sex man height 180 设置多个field
hmget person name age sex height 获取多个field
hkeys person 查看person里有多少个field
hdel person name height 删除person的name和height域

list类型:类似双端队列?

左侧插入数据,格式:lpush key value1 value2 ....
lpush list 1 2 3 4
右侧插入数据:rpush ...
左侧查询数据:lrange(没有rrange)
lrange list 0 3 结果为 4,3,2,1,0和3是索引

linsert list before 3 30 在3前面插入个30

linsert list after 3 300 在3后面加入个300

lrange list 0 -1 获取从后到前

lset list 2 3000 将2改为3000

删除:lrem key count value 将key域列表中,count次,值为value的删掉
count:0表示所有,正数是从头开始,负数是从尾开始,删|count|个
lrem list 2 c 从头开始,删两个c
lrem list -3 a 从尾开始,删三个c

set类型:无序集合

set:无序,不重复
sadd myset 1 2 3 7 5 8 1 2 3 设置集合,添加数据

sadd myset zhangsan lisi wangwu

smembers myset 结果:

python就业班第34天----单元测试、Redis、集群

sadd myset 1 myset添加1
srem myset 7 删除myset的7

删除集合用del
del myset

zset:有序类型

权重:zadd
zadd myzset 10 zhangsan 20 lisi 30 wangwu 10:zhangsan,20:lisi,30:wangwu

zrange myzset 0 -1 查看权重

zrangebyscore myzset 19 21 查看在19~21之间的

zscore myzset wangwu 推导wangwu的权重

zrem myzset zhangsan 删掉zhangsan

zrange myzset 0 -1


redis在python中使用

3个步骤:

  • 1.导入redis类
  • 2.创建redis对象
  • 3.调用方法

例:

# 1.导入redis类
import redis
# 2.创建redis对象,decode_response=True,默认就会解码
# 形参是默认的,可以都不写,decode_response是解码,不然读出来是字节码形式
redis_store = redis.StrictRedis(host="127.0.0.1",port=6379,decode_response=True)

# 3.调用方法
# 存储数据
redis_sotre.set("name","laowang")
# 获取数据
value = redis_store.get("name")
print(value)
# 修改数据
redis_store.set("name","banzhang")
value = redis_store.get("name")
print(value)
# 删除数据
redis_store.delete("name")
value = redis_store.get("name")
print(value)

python就业班第34天----单元测试、Redis、集群
redis.StrictRedis()按 ctrl + p查看参数,如果不写响应解码 decode_response=True,则数据以字节码形式显示'b'laowang


集群

主从概念:一个master可以有多个slave,一个slave可以有多个slave,如此下去就是集群

主从搭建:

pass,晚点专门写另一篇文章

配置主从:

  • 1.ifconfig查看ip
  • 2.修改/etc/redis/redis.conf
  • 3.将127.0.0.1改成ip(bind的那行)
  • 4.如果继承搭建不了,将protected-mode改为no

配置文件目录为/usr/local/redis/redis.conf(Ubuntu16是这个,18和其它的系统我就不知道了)
sudo cp /usr/local/redis/redis.conf /etc/redis/
将redis.conf拷贝个,目标文件slaveof.conf(同目录,放到另一台服务器,如果没有改下端口也行)
配置slaveof,主人是谁: slave 主人ip 主人端口

启动起来,可指定配置文件:
sudo redis-server redis.conf
sudo redis-server slaveof.conf

查看是否有主从:redis-cli -h ip info Relication

然后主从分离。主人负责在redis写,奴隶负责读
redis-cli -h ip -p 端口

奴隶和主人都启动

主人即可写,也可以读(基本不用);奴隶只能做读


如果同时的访问量过大(1000w),主服务器肯定就会挂掉,大公司都会有很多的服务器(华东地区、华南、港澳台)

当请求来时,先由负载均衡服务器处理,把请求转发到另外的一台服务器上

负载均衡服务器:Negix

分类:
软件层面(一台电脑,靠软件启动多个redis服务),不能应付高并发
硬件层间(多台电脑,每个都启动一个或多个redis服务),可以应付高并发

集群搭建:
在conf搞下面代码
port 端口号
bind ip地址
daemonize yes // 守护进程,是否运行后台进程
pidfile ??.pid
cluster -enabled yes // 是否允许创建集群
cluster -config -file //配置文件
cluster -node -timeout 15000 //超时
appendonly yes // 是否允许其他加入进来

必须三个以上,才能成为集群,不然搭建不起来

配置好6个conf后,启动服务,然后搞rb
redis-trib.rb

然后创建集群:一旦创建好后,主从就会给你分配好了,会提示你要不要接受这种配置
会跳出来个有个slots,槽的意思,一个是0~16383,它计算你要搞的内容在哪个槽里面,你的在哪个槽,它就给你弄到对于的服务器

槽的算法:CRC16算法

跟python交互

from rediscluster import *
if __name__ == '__main__':
  try:
    # 构建所有的节点,Redis会使⽤CRC16算法,将键和值写到某个节点上
    startup_nodes = [
        {'host': '192.168.26.128', 'port': '7000'},
        {'host': '192.168.26.130', 'port': '7003'},
        {'host': '192.168.26.128', 'port': '7001'},
    ]
    # 构建StrictRedisCluster对象
    src=StrictRedisCluster(startup_nodes=startup_nodes,decode_responses=True)
    # 设置键为name、值为itheima的数据
    result=src.set('name','itheima')
    print(result)
    # 获取键为name
    name = src.get('name')
    print(name)
  except Exception as e:
    print(e)