Redis常用操作
from redis import Redis
# from redis import ConnectionPool
conn = Redis() # 实例化对象,创建连接对象
# conn.set('name','dxx') # 单个插入
# for i in range(1,100):
# conn.set("the %s key"%i, 'the %s value'%i,ex=i) # 循环插入
# ret = conn.get("the 80 key") # 取不到是为None 无法指定默认值
#
# print(ret)
# conn.set('name','希希') # 单个插入 中文会自动以utf8编码转码为bytes类型
#
# for i in range(1,100):
# conn.set("%skey"%i,'%svalue'%i)
from app01.Redis_POOL import POOL # 连接池做成单例
conn = Redis(connection_pool=POOL)
print(conn.get("name").decode("utf8"))
# 字符串操作
conn.set('age',19,ex=10,xx=True)
conn.setex('hobby',10,'basketball') # (key,time, value)
# 批量添加,传字典
conn.mset({'k1':'v1','k2':'v2'})
# 批量取值
print([ res.decode("utf8") for res in conn.mget(['k1', 'k2'])])
# 追加
conn.setrange('k1',1,'pp')
conn.set('k3','10')
#
conn.setrange('k3',2,'10')
# #
print(conn.get('k3'))
# 重点 (网站访问量)
conn.incr('ask_total',amount=1) # 递增 可指定频率为负数,表示递减
conn.decr('ask_total') # 与上相反
conn.append('ask_total',22) # 向原有值后拼接
#hash操作
conn.hset('hax1','k1','v1') # 存
print(conn.hget("hax1", 'k1')) # 取
#批量存取
conn.hmset('hax1',{'k2':'v2','k3':'v3'})
print(conn.hmget('hax1', ['k1', 'k2',]))
print(conn.hmget('hax1', 'k1', 'k2')) # 内部做判断是否列表
print(conn.hgetall('hax1')) # {b'k1': b'v1', b'k2': b'v2', b'k3': b'v3'}
print(conn.hgetall('hax1')[b"k1"]) # b'v1'
print(conn.hlen('hax1')) # 3 列表/数组长度
conn.hdel('hax1','k1') # 哈希删除
print(conn.hget('hax1','k1')) # 再查询
conn.hset('hax1','k2',22)
conn.hincrby('hax1','k2',amount=-10) # 哈希递增 或者递减
print(conn.hget('hax1','k2'))
# 重点
hscan
hscan_iter
for i in range(1,1000):
conn.hset('hax2','%skey'%i,'%svalue'%i)
# match 过滤条件 count 取出数据个数
print(conn.hscan('hax2',10,match='350value',count=20)) # (26, {})
print(conn.hscan('hax2',10,match='350',count=20)) # (26, {})
print(conn.hscan('hax2',10,match='350key',count=20)) # (26, {b'350key': b'350value'})
#
conn.hscan_iter('hax2',count=10)
genrator = conn.hscan_iter('hax2',count=10) # 产生迭代器,迭代器能产生的数据不因count值而变化,
# count的作用是限制一次向redis要多少数据,用完了再要
print(genrator) # 打印的生成器内存地址
print('生成器长度:',len(list(genrator))) # 会取完hax2中所有的数据
for i in genrator:
print(i) # 由于上方len(list(genrator))已经将生成器迭代完,故迭代器已经无元素可迭代,无值打印
# redis列表操作
conn.lpush('h1','11') # 列表左追加
conn.rpush('h1','10','9') # 列表右追加
print(conn.linsert('h1','AFTER','11',99)) # 在元素11后面插入99
print(conn.linsert('h1','AFTER','11','99')) # 在元素11前面插入99
#如果列表中有多个'11',那么插在第一个'11'的前面或者后面
print(conn.llen('h1'))
conn.lset('h1',1,'1111')
conn.lrem('h1',-5,11)
#lrem(name,count,value)
# count的正负表示从头开始还是从尾巴开始删除和value相同的值,0表示删除所有相同的
#count的数字表示删除几个
print(conn.lindex('h1', 3)) # 取列表索引为3的值
print(conn.lrange('h1', 1, 5)) # 取列表索引1-5的元素,闭区间
print(conn.lrange('h1',0,conn.llen('h1'))) # 取列表所有元素
#blpop 重点
print(conn.lpop('h1'))
print(conn.lpop('h1')) # 从左删除一个元素
print(conn.rpop('h1')) # 从右删除一个元素
while True:
print(conn.blpop('h1')) # 取完了会在这里阻塞,等待有下一个值被添加,你会不会想到队列呢?
# 是的,它可以实现队列的效果,可以实现分布式
# 可以同时开多个客户端去blpop,也可以同时开多个客户端去新增
# 自定义列表生成器
def scan_list(name,count=10):
index = 0
while True:
data_list = conn.lrange(name,index,count)
if not data_list:
return
index+= count
count+=index
for item in data_list:
yield item
sa_list = scan_list('h1',5)
for i in sa_list:
print(i)
conn.delete('name') # 删除
print(conn.exists('hax2')) # 返回0或1
print(conn.keys('k?')) # 模糊匹配
print(conn.keys('k*'))
conn.rename('k1','kk') # 重命名
# 利用管道实现事务操作
pipe = conn.pipeline(transaction=True)
pipe.multi()
pipe.set('name','egon')
pipe.lpush('h1','aa')
pipe.execute()
事务的四大特性:
1 、原子性
事务是数据库的逻辑工作单位,事务中包含的各操作要么都做,要么都不做
2 、一致性
事 务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。因此当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果数据库系统 运行中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已写入物理数据库,这时数据库就处于一种不正确的状态,或者说是 不一致的状态。
3 、隔离性
一个事务的执行不能其它事务干扰。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。
4 、持续性
也称永久性,指一个事务一旦提交,它对数据库中的数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其执行结果有任何影响。
应用场景:
一、利用原生redis实现网站流量统计
由于是全局统计,Django中我们需要自定义中间件来实现
from redis import Redis
from django.middleware.common import MiddlewareMixin
Conn = Redis()
class CountVisitorMiddle(MiddlewareMixin):
def process_request(self,request):
num = Conn.hget('count_visitor','number')
if num:
Conn.hset('count_visitor','number',int(num.decode("utf8"))+1)
else:
Conn.hset('count_visitor', 'number', 1)
配置文件中配置:
MIDDLEWARE = [
.......其他中间件.........
'app01.CountCustomerMiddleWare.CountVisitorMiddle',
]
视图函数中使用:
from django.shortcuts import render
# Create your views here.
from app01.redis_hander import Conn
def index(request):
visitor_number = Conn.hget('count_visitor','number').decode('utf8')
return render(request,"index.html",locals())
当然,django有更好的封装来让我们使用基于redis的缓存实现
二、利用Django基于redis的缓存实现网站流量统计
配置文件中配置缓存信息:
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache", # cache存储引擎为redis数据库
"LOCATION": "redis://127.0.0.1:6379", # redis服务器地址
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100} # redis数据库连接池大小限制
# "PASSWORD": "123",
}
}
}