day40-redis数据库主要语法-及与mysql结合用法示例
redis数据库详细语法及说明见[http://redisdoc.com/]
下面仅对其常见的五种数据类型的语法进行介绍
1字符串
setex(如果键存在才能设置值)
setnx(如果键不存在才能设置值);
mset(一次设置多个键值对)
mget(一次获取多个键值对);
incr str1 将str1中存储的数字值增1
getset(拿到键之前的值并对其进行新的赋值)
gitbit(取指定位上的比特看是否为0)
setbit(设置或清除指定偏移量上的比特)
setbit ab 128 1设置ab键的第128位为1,其余为0
type 键:可以查看键的数据类型
object encoding 键 :查看底层的数据类型
2哈希表
哈希表:字典里面的值又是一个字典,最适合用来保存对象
hset stu1 stuid 1001
hset stu1 name xiaoming
hset stu1 gender male
hset stu1 birth 1999-12-31
hset stu1 addr chengdu
type stu1 # hash
object encoding stu1 # ziplist
hget stu1 gender # 取一个值
hgetall stu1 #取所有
hvals stu1 # 取所有的值
同时设置多个值
hmset stu2 stuid 1002 name wangdachui addr mianyang gender male
hmget stu2 name gender #同时获取stu2的两个值
hdel stu2 gender #删除stu2的性别(只删除字段)
hexists stu2 gender #判断存在否
hset stu1 fav 100
hset stu2 fav 95.23
hincrby stu1 fav 50 #给学生1增加点赞数50
hincrbyfloat stu2 fav 100.234 #给学生2的点赞数增加100.234
hkeys stu1 # 取stu1的所有键
3列表
列表中的数据结构分为栈和队列两种
经典数据存储结构:
3.1栈
栈(stack) - FILO - 先进后出 - lpush + lpop/rpush + rpop
lpush list1 100 200 300 400 500 600
从左边拿
lpop list1 #600
。。。
lpop list1 #100(先进后出)
3.2队列
队列(queue) - FIFO - 先进先出- lpush + rpop/rpush + lpop
lpush list1 100 200 300 400 500 600
从右边拿
rpop list1 # 100
...
rpop list1 # 600(后进后出)
3.3列表基本语法
lpush list1 100 200 300 400 500 #给列表在左边放了五个数据
lrange list1 0 -1 #查看列表下标为0到-1的数据(500 400 ...)
rpush list2 100 200 300 400 500 #给列表在右边放了五个数据
lrange list1 0 -1 #查看列表下标为0到-1的数据(100 200 ...)
lpop list1#从列表的左边取一个数据(500)
rpop list1 #从列表的右边取一个数据(100)
rpop list1 #从列表的右边取一个数据(200)
lpush list1 100 200 300 400
lindex list13 取出下标为3的元素(100)
llen list1 看列表的长度
lrange list2 0-1 查看list2的两个元素
brpop(阻塞式从右边取元素)
brpop list2 5 5秒内取list2中的元素,如果超过5秒没有取到东西就返回nil和等待时长
4集合
set
集合中不能放重复元素
sadd set1 100 200 100 #创建一个集合
smembers set2 #查看集合中的所有元素
sinter set1 set2 # 求交集
sdiff set1 set2 #求差集
sunion set1 set2 # 求并集
srem set1 100 #删除100这个元素
sismember set1 200 # 查看200是否在集合1中
scard set1 #查看集合中元素的个数
spop set1 #随机取set1中的一个元素并将其删除
srandmember set2 2 随机取随机个数的函数
5有序集合
zset
zadd paihangbang 100 laowang 550 xiaoming 200 sss 500 qqq #创建一个排行榜集合
zrange paihangbang 0 -1#将集合的下标0到-1的元素从小到大排序
zrevrange paihangbang 0 -1 同上,不过是从大到小排序
6读写分离配置:
主机配置:redis-server --requirepass 设置密码 >redis.log 2 > redis-error.log &
从机配置: redis-server --slaveof 主机ip 端口--masterauth 主机设置的密码 > redis.log 2>redis -error.log &
redis-cli (进入从机)
作为从机连接主机
slaveof no one #解除主从配置
history:查看历史命令
! 历史命令前的id(如! 997): 将这个命令在执行一遍
7在python中给mysql查询的文件分页
import pymysql
from pymysql.cursors import DictCursor
con = pymysql.connect(host='localhost', port=3306,
database='hrs', charset='utf8',
user='root', password='123456', autocommit=True)
class Emp():
def __init__(self,no,name,job,sal):
self.no=no
self.name=name
self.job=job
self.sal=sal
def __str__(self):
return f'{self.no}-{self.name}-{self.job}-{self.sal}'
def main():
page=int(input('页码:'))
size=int(input('页面大小:'))
try:
with con.cursor() as cursor: 元祖形式
cursor.execute('select * from tb_emp limit (%s,%s)',((page-1)*size,size)) #显示从第几页看起,一页显示多少行
for result in cursor.fetchall(): #返回元祖
emp=Emp(*result)
print(emp)
with con.cursor(DictCursor) as cursor: 字典形式
cursor.execute('select * from tb_emp limit (%s,%s)', ((page - 1) * size, size))
for result in cursor.fetchall(): #返回字典
emp=Emp(**result)
print(emp)
finally:
con.close()
8随机生成验证码并发送短信(用redis控制一个小时只能发送三次)
import io
import json
import time
import random
import requests
import redis
def gen_code(length=6):
"""生成指定长度的验证码"""
result = io.StringIO()
for _ in range(length):
result.write(str(random.randint(0, 9)))
return result.getvalue()
def send_messag_example(tel, code):
"""发送短信"""
resp = requests.post(
url='http://sms-api.luosimao.com/v1/send.json',
auth=('api', 'e67b65751337d36224b26074ceb8a421'),
data={
'mobile': tel,
'message': f'您的验证码为{code}。【铁壳测试】'
# 'message': f'猜猜我是谁。【铁壳测试】'
},
timeout=3,
verify=False
)
return json.loads(resp.content)
def my_main():
tel = input('请输入手机号:')
cli = redis.StrictRedis(host='112.74.61.160', port=6379,
password='1qaz2wsx')
if not cli.exists(tel):
result = send_messag_example(tel, gen_code())
print(result)
if result['error'] == 0:
print('短信发送成功')
cli.set(tel, 1, ex=3600)
elif int(cli.get(tel)) < 3:
result = send_messag_example(tel, gen_code())
print(result)
if result['error'] == 0:
print('短信发送成功')
cli.incr(tel)
else:
print('请不要频繁发送短信验证码(1小时只能发送3次)')
my_main()
9 python中使用redis
1.连接redis服务器
2.创建连接对象
cli=redis.StrictRedis(ip,端口,redis登陆密码)
def main():
cli = redis.StrictRedis(host='112.74.61.160', port=6379,
password='1qaz2wsx')
try:
if cli.ping():
print('连接成功')
print(cli.keys('*'))
print(cli.set('username', 'hellokitty'))
print(cli.expire('username', 120))
print(cli.get('username'))
time.sleep(5)
print(cli.ttl('username'))
cli.sadd('set1', '100', '200', '100', '200', '500')
print(cli.scard('set1'))
except:
print('连接出错')
finally: #可能有错
cli.shutdown(save=True)
10redis和mysql结合提高程序效率示例
序列化 - 把对象转换成字符或字节序列 - 串行化/腌咸菜
反序列化 - 把字符或者字节序列还原成对象 - 反串行化
python中要实现对象的序列化和反序列化有三种方案:
-json - load/loads / dump/dumps - 字符序列
-pickle - load / loads /dump/dumps - 字节序列(使用较多)
提高效率原理:redis将数据存放在内存中,mysql存放在硬盘中,从运存中提取数据效率远远高于从硬盘中提取;
取数据时,先用redis去内存中查找是否存在数据,如若存在就直接提取,不存在,就利用mysql从数据库提取;
最后在利用redis将数据存入内存中,从而方便下次查找,提高效率;
可以将常用数据存入redis这样能大大提高效率;
例如选择每个省及其下的县市时,省为常用数据,故常将省存在内存中
import pickle
import time
import pymysql
import redis
class District:
""行政区域"""
def __init__(self,distid,name):
self.distid=distid
self.name=name
def __str__(self): #打印函数
return self.name
def __repr__(self): # 查看函数
return self.name
def my_dis():
# 记录程序执行起始时间
begin=time.time()
cli=redis.StrictRedis(host='120.77.222.217',
port=6379,password='1qaz2wsx')
# 优先从缓存中读取数据,如果缓存没有所需数据,才连接数据库进行查询
if cli.exists('provinces'):
provinces=pickle.loads(cli.get('provinces'))
# 直接从缓存中通过键获取数据并反序列化成Python中的对象
else:
provinces=[]
con=pymysql.connect(host='localhost', port=3306,
database='hhrs', charset='utf8',
user='root', password='123456')
try:
with con.cursor() as cursor:
# 从数据库中查询省级行政区域
cursor.execute('select `distid`,`name` from `tb_district` where `pid` is null')
# 将查询结果放入列表容器
for dist_tuple in cursor.fetchall():
# 将元祖数据解包生成对象
dist=District(*dist_tuple)
# 将对象添到列表
provinces.append(dist)
# 将列表序列化(pickle)然后放入redis中缓存
cli.set('provinces',pickle.dumps(provinces))
finally:
con.close()
# 记录程序执行结束时间
end=time.time()
print(f'执行时间:{end-begin}秒')
print(provinces)