1.介绍和安装
1.介绍:缓存数据库(大部分时间做缓存,不仅仅可以做缓存),非关系型数据库(区别于mysql关系型数据库)。原来从mysql中查的数据,现在可以从Redis中查,可以提高效率。
c语言写的 服务(监听端口),用来存储数据的,数据是存储在内存中,取值,放值速度非常快,最高可达10万qps。
没有表关系,都是通过key-value形式存储
nosql:非关系型的数据库
2.redis速度快的原因:
1.纯内存操作
2.网络模型使用的IO多路复用(epoll)(可以处理的请求数更多)
3.6.x之前,单进程,单线程架构,没有线程进程间切换,更少的消耗资源
3.版本:最新是7.x,公司内5.x较多。
4.安装:
mac:源码编译安装
linux:源码编译安装
win:微软自己,基于源码,改动,编译成安装包
最新5.x版本 https://github.com/tporadowski/redis/releases/
最新3.x版本 https://github.com/microsoftarchive/redis/releases
安装步骤:
安装完成后会释放两个命令:
redies-server:服务端的启动命令
redies-cli:客户端的启动命令
redis.windows-service.conf:配置文件
配置文件中的内容:
bind 127.0.0.1 服务,跑在的地址
port 监听的端口
启动服务的两种方式:
方式一:在服务中右键,开始
方式二:使用命令
redis-server 指定配置文件,如果不指定会默认
5.客户端连接:
方式一:redis-cil 默认连接本地的6379端口(一般用来连接本地的redis)
方式二:redis-cli 地址 -p 端口(一般用来连接远程的redis)
6.使用图形化客户端操作:
Navicat不支持redis,我们推荐使用resp
安装(一路下一步):
连接redis:
方式一(写起来较为麻烦):
方式二(推荐采用):
通讯化界面本地默认存在16个库,我们数据默认的都是在第一个。我们使用命令(后面详细讲)加入一个数据{name:max},在可视化界面上也可以显示出来:
2.python操作redis、普通连接和连接池
2.1python操作redis
python操作redis时相当于客户端,首先我们需要安装模块redis:
pip install redis
1.导入模块Redis
from redis import Redis
2.实例化得到对象
conn = Redis(host='127.0.0.1', port=6379)
3.使用conn,操作redis,获取name的值,获取到的是二进制类型
res = conn.get('name')
print(res) # b'max'
4.设置值
conn.set('age',18)
2.2 普通连接和连接池
1.连接池:redis为了保证自己的效率,往往不会允许太多的请求。一个池子里有两个用来连接Redis的线程,那么只要同时有三个或以上的线程来连接redis,那么拿不到请求的线程就需要等待,目的就是不允许有太多的连接,这也是Redis为了保证自己性能的手段。
2.django连接池:django默认不带有连接池的概念,如果有100个线程同时访问(100次rom),那么django就是同时承受100的并发量。并发量过高会导致mysql性能不高。但是如果我们就想在django上使用半连接池,我们需要导入模块,然后再加入一下配置:
1.导入模块:
pip install django-db-connection-pool
2.在数据库按照如下配置:
DATABASES = {
"default": {
"ENGINE": "dj_db_conn_pool.backends.mysql",
"NAME": "数据库名",
"USER": "用户名",
"PASSWORD": "密码",
"HOST": "127.0.0.1",
"PORT": "3306",
"CHARSET": "utf8",
"POOL_OPTIONS" : {
"POOL_SIZE": 10, # 池子大小
"MAX_OVERFLOW": 10,
"RECYCLE": 24 * 60 * 60 # 用多少次回收
}
}
}
2.3 使用python多线程连接redis
方式一:传统方案,开100个线程操作:
from redis import Redis
from threading import Thread
def index():
conn = Redis(host='127.0.0.1', port=6379)
print(conn.get('name'))
for i in range(100): # 产生100个线程,分别执行index任务
t = Thread(target=index) # 注意方法名不要加括号
t.start()
方式二:使用连接池连接:
import redis
from threading import Thread
def index():
conn = Redis(host='127.0.0.1', port=6379)
print(conn.get('name'))
POOL = redis.ConnectionPool(max_connections=20, host='127.0.0.1',
port=6379) # 产生一个大小为20的redis连接池,指定端口,地址,池中所有的连接都是指向这个端口和地址。这句代码不能写在for循环中,如果写在循环中每循环一次会建立一个池,从池中拿一个连接,性能会更低
def task():
conn = redis.Redis(connection_pool=POOL)
print(conn.get('name')) # b'max'
for i in range(100):
t = Thread(target=task)
t.start()
"""
如果循环10000次,产生链接的次数远大于池子里连接的次数,但是此时拿不到连接的线程并不会阻塞而是直接报错,因为请求的数量远大于连接池内连接的数量
"""
为了防止产生多个连接池的现象,我们需要将连接池生成一个单例,也就是只产生一个连接池,以后请求只能从连接池中拿:
pool.py:
import redis
POOL = redis.ConnectionPool(max_connections=20, host='127.0.0.1',
port=6379) # 产生一个大小为20的redis连接池,指定端口,地址,池中所有的连接都是指向这个端口和地址
连接池.py:
import redis
from threading import Thread
def task():
from pool import POOL # 做成模块后,我们每次导入的都是那一个POOL
conn = redis.Redis(connection_pool=POOL)
print(conn.get('name'))
for i in range(10):
t = Thread(target=task)
t.start()