非关系型数据:没有关系的数据库
redis就是一个字典,都是key,value形式的,
值支持五大数据类型
{
key: ‘’,
key: [],
key: {},
key: 集合,
key: 有序集合
}
菜鸟教程
- 启动redis服务端,以便连接redis服务端
- 启动客户端
另起cmd,原来的不要关闭,使用cmd和服务端进行交互
- 使用python连接redis服务端
- 字符串操作
import redis
import time
conn = redis.Redis(host='localhost', port=6379, decode_responses=True)
conn.set('name', 'wendy')
print(conn.get('name'))
print(conn.exists('name'))
conn.expire('name', 2) # 2秒后删除‘name',
time.sleep(3)
print(conn.exists('name'))
conn.mset({'hobby1': 'swimming', 'hobby2': 'running'})
print(conn.mget(['hobby1', 'hobby2']))
运行结果
wendy
1
0
['swimming', 'running']
- hash操作
redis的key字段只能存字符串类型,单个key能存512M长度,key里可以存文章介绍等
- 字典中一个键值对hset
import redis
conn = redis.Redis(host='localhost', port=6379, decode_responses=True)
conn.hset('wendy', 'hobby', 'swimming')
print(conn.hget('wendy', 'hobby'))
print(conn.hgetall('wendy'))
print(type(conn.hgetall('wendy')))
运行结果
swimming
{'hobby': 'swimming'}
<class 'dict'>
- 多个键值对hmset
import redis
conn = redis.Redis(host='localhost', port=6379, decode_responses=True)
conn.hmset('laura', {'hobby1': 'movie', 'hobby2': 'reading', 'hobby3': 'baseketball'})
print(conn.hmget('laura', ['hobby1', 'hobby3']))
print(conn.hgetall('laura'))
运行结果
['movie', 'baseketball']
{'hobby1': 'movie', 'hobby2': 'reading', 'hobby3': 'baseketball'}
- 值是字典,字典中的值是字典,redis只能支持一层字典,使用json格式进行传输,
import redis
import json
conn = redis.Redis(host='localhost', port=6379, decode_responses=True)
font_dict = {'hobby1': 'singing', 'hobby2': 'dancing'}
ret = json.dumps(font_dict, ensure_ascii=False) # 序列化
conn.hset('linda', 'hobby', ret)
print(conn.hget('linda', 'hobby'))
print(type(conn.hget('linda', 'hobby')))
print(json.loads(conn.hget('linda', 'hobby')))
print(type(json.loads(conn.hget('linda', 'hobby'))))
运行结果
{"hobby1": "singing", "hobby2": "dancing"}
<class 'str'>
{'hobby1': 'singing', 'hobby2': 'dancing'}
<class 'dict'>
- 连接池
由于redis是线程安全的,所有数据库用一个连接也是安全的,可以建立连接池,请求来了直接在连接池中已经创建好的连接进行操作,这样不用每次都重新开连接,时间成本比较大。
新建连接池
import redis
pool = redis.ConnectionPool(host='localhost', port=6379, decode_responses=True, max_connections=5)
使用连接池
import redis
from utils.redis_pool import pool
conn = redis.Redis(connection_pool=pool)
conn.hset('name3', 'lin', 'female')
print(conn.hget('name3', 'lin'))
运行结果
female
- redis事务
redis事务特点是批量执行,mysql的事务是原子性
redis命令是原子性
from utils.redis_pool import pool
import redis
conn = redis.Redis(connection_pool=pool)
pipe = conn.pipeline() # 创建一个事务对象
try:
pipe.set('name', 'dave')
pipe.set('name2', 'lende', 'run')
pipe.set('name3', 'wend') # 把所有操作放入缓存队列
pipe.execute() # 执行事务
except Exception as e:
print(e)
print(conn.get('name'))
print(conn.get('name3'))
运行结果
Command # 2 (SET name2 lende EX run) of pipeline caused error: value is not an integer or out of range
dave
wend
第二条执行失败不影响第一条和第一条成功,也就是redis的事务不是原子性的
- redis订阅者发布者模式
订阅者
import redis
from utils.redis_pool import pool
conn = redis.Redis(connection_pool=pool)
pubsub = conn.pubsub() # 生成一个订阅者对象
pubsub.subscribe('wendy') # 订阅一个消息,实际上就是监听这个键
while True: # 死循环一直等待监听结果
print('working~~')
msg = pubsub.parse_response() # 解析消息
print(msg)
发布者
import redis
from utils.redis_pool import pool
conn = redis.Redis(connection_pool=pool)
conn.publish('wendy', 'hehe')
conn.publish('wendy', '1111')
运行结果
working~~
['subscribe', 'wendy', 1]
working~~
['message', 'wendy', 'hehe']
working~~
['message', 'wendy', '1111']
working~~