快速上手非关系型数据库Redis

一、Redis介绍

1.非关系型数据库,纯内存操作,key-value存储,性能很高,可持久化(内存---->保存到硬盘上)

2.缓存,计数器,验证码,geo地理位置信息,发布订阅,独立用户统计

3.五大数据类型:字符串,列表,hash,集合,有序集合

4.6.x之前版本是单线程、单进程
qps(每秒查询量):10w并发,实际6w并发
为什么这么快?

  • 纯内存操作
  • 使用了io多路复用的模型,epoll(select,poll,epoll)
  • 避免了线程间切换的浪费

5.安装
官方提供了源码(C语言),编译安装
编译型语言,如果要执行,需要在不同平台编译成不同平台的可执行文件

linux版本安装
编译(gcc),编译成可执行文件,就可以运行
1、官网下载:安装包或是绿色面安装
2、安装并配置环境变量
官网,下载完是源代码:C语言源码
最稳定:6.x,最新7.x
中文网,最新只到5.x

wget http://download.redis.io/releases/redis-3.0.6.tar.gz
tar xzf redis-3.0.6.tar.gz
cd redis-3.0.6
make
# 启动服务端
src/redis-server
# 启动客户端
src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"

windows版本安装
不支持windows,但有人在原来的基础上编写了windows版本
下载3.x版本或5.x版本 ,下载完一路下一步即可
windows上自动做成服务,启动关闭服务,监听的端口是:6379
在这里插入图片描述
连接方式:

  • 使用命令启动服务端
redis-server 配置文件
  • 客户端连接:命令窗口
redis-cli
  • python代码连接
  • 图形化客户端,有很多
    redis-desktop-manager:安装一路下一步
    可以连远端

6.QT(平台):使用C/C++语言在平台上开发---->图形化界面软件(GUI)
pyqt:在qt平台上使用python代码写图形化界面
Tkinter

7.django 2.0.7以后,如果还使用pymysql连mysql,源码不兼容,改源码
mysqlclient:什么都不用配,直接用,不需要改源码

8.软件运行,会监听某个端口,客户端通过ip+端口访问
2的16次方 = 一共65535个
1-1024 系统使用

9.redis的key和string类型value限制均为512MB

10.redis VS mysql
redis: 内存数据库(读写快)、非关系型(操作数据方便、数据固定)
mysql: 硬盘数据库(数据持久化)、关系型(操作数据间关系、可以不同组合)
大量访问的临时数据,才有redis数据库更优

11.redis VS memcache
redis: 操作字符串、列表、字典、无序集合、有序集合 | 支持数据持久化(数据丢失可以找回(默认持久化,主动持久化save)、可以将数据同步给mysql) | 高并发支持
memcache: 操作字符串 | 不支持数据持久化 | 并发量小

12.启动服务

前提:前往一个方便管理redis持久化文件的逻辑再启动服务:dump.rdb
1)前台启动服务
>: redis-server

2)后台启动服务
>: redis-server --service-start
注)Linux系统后台启动(或是修改配置文件,建议采用方式)
>: redis-server &

3)配置文件启动前台服务
>: redis-server 配置文件的绝对路径

4)配置文件启动后台服务
注)windows系统默认按Redis安装包下的redis.windows-service.conf配置文件启动
>: redis-server --service-start
注)Linux系统可以完全自定义配置文件(redis.conf)后台启动
>: redis-server 配置文件的绝对路径 &
"""

"""
windows系统
1)前台启动
	i)打开终端切换到redis安装目录
	>: cd C:\Apps\Redis
	
	ii)启动服务
	>: redis-server redis.windows.conf

2)后台启动
	i)打开终端切换到redis安装目录
	>: cd C:\Apps\Redis
	
	ii)启动服务(后面的配置文件可以省略)
	>: redis-server --service-start redis.windows-service.conf

13.密码管理

1)提倡在配置文件中配置,采用配置文件启动
requirepass 密码

2)当服务启动后,并且连入数据库(redis数据库不能轻易重启),可以再改当前服务的密码(服务重启,密码重置)
config set requirepass 新密码

3)已连入数据库,可以查看当前数据库服务密码
config get requirepass

14.连接数据库

1)默认连接:-h默认127.0.0.1-p默认6379-n默认0-a默认无
>: redis-cli

2)完整连接:
>: redis-cli -h ip地址 -p 端口号 -n 数据库编号 -a 密码

3)先连接,后输入密码
>: redis-cli -h ip地址 -p 端口号 -n 数据库编号
>: auth 密码

15.切换数据库

1)在连入数据库后执行
>: select 数据库编号

16.关闭服务

1)先连接数据库,再关闭redis服务
>: redis-cli -h ip地址 -p 端口号 -n 数据库编号 -a 密码
>: shutdown

2)直接连接数据库并关闭redis服务
>: redis-cli -h ip地址 -p 端口号 -n 数据库编号 -a 密码 shutdown

17.清空redis数据库

1)连接数据库执行
>: flushall

18.数据持久化

1)配置文件默认配置
save 900 1  # 超过900秒有1个键值对操作,会自动调用save完成数据持久化
save 300 10  # 超过300秒有10个键值对操作,会自动调用save完成数据持久化
save 60 10000  # 超过60秒有10000个键值对操作,会自动调用save完成数据持久化

2)安全机制
# 当redis服务不可控宕机,会默认调用一下save完成数据持久化(如果数据量过大,也可能存在部分数据丢失)

3)主动持久化
>: save  # 连入数据库时,主动调用save完成数据持久化
>
注:数据持久化默认保存文件 dump.rdb,保存路径默认为启动redis服务的当前路径

19.redis相关配置

1)绑定的ip地址,多个ip用空格隔开
bind 127.0.0.1

2)端口,默认6379,一般不做修改
port 6379

3)是否以守护进程启动,默认为no,一般改为yes代表后台启动(windows系统不支持)
daemonize no

4)定义日志级别,默认值为notice,有如下4种取值:
	debug(记录大量日志信息,适用于开发、测试阶段)
	verbose(较多日志信息)
	notice(适量日志信息,使用于生产环境)
	warning(仅有部分重要、关键信息才会被记录)
loglevel notice

5)配置日志文件保持地址,默认打印在命令行终端的窗口上
	如果填写 "./redis.log" 就会在启动redis服务的终端所在目录下,用redis.log记录redis日志
logfile ""

eg)终端首先切断到log文件夹所在目录(一般就可以采用redis的安装目录,也可以自定义),再启动reids服务
logfile "./log/redis.log"

6)数据库个数,默认是16个,没特殊情况,不建议修改
databases 16

7)数据持久化
save 900 1  # 超过900秒有1个键值对操作,会自动调用save完成数据持久化
save 300 10  # 超过300秒有10个键值对操作,会自动调用save完成数据持久化
save 60 10000  # 超过60秒有10000个键值对操作,会自动调用save完成数据持久化

8)数据库持久化到硬盘失败,redis会立即停止接收用户数据,让用户知道redis持久化异常,避免数据灾难发生(重启redis即可),默认为yes,不能做修改
stop-writes-on-bgsave-error yes

9)消耗cpu来压缩数据进行持久化,数据量小,但会消耗cpu性能,根据实际情况可以做调整
rdbcompression yes

10)增持cpu 10%性能销毁来完成持久化数据的校验,可以取消掉
rdbchecksum yes

11)持久化存储的文件名称
dbfilename dump.rdb

12)持久化存储文件的路径,默认是启动服务的终端所在目录
dir ./

13)reids数据库密码
requirepass 密码

20.Redis数据类型

"""
数据操作:字符串、列表、哈希(字典)、无序集合、有序(排序)集合
	有序集合:游戏排行榜
	
字符串:
	set key value
	get key
	mset k1 v1 k2 v2 ...
	mget k1 k2 ...
	setex key exp value
	incrby key increment
	
列表:
	rpush key value1 value2 ...
	lpush key value1 value2 ...
	lrange key bindex eindex
	lindex key index
	lpop key | rpop key
	linsert key before|after old_value new_value
	
哈希:
	hset key field value
	hget key field
	hmset key field1 value1 field2 value2 ...
	hmget key field1 field2
	hkeys key
	hvals key
	hdel key field
	
集合:
	sadd key member1 member2 ...
	sdiff key1 key2 ...
	sdiffstore newkey key1 key2 ...
	sinter key1 key2 ...
	sunion key1 key2 ...
	smembers key
	spop key
	
有序集合:
	zadd key grade1 member1 grade2 member2 ...
	zincrby key grade member
	zrange key start end
	zrevrange key start end
"""

二、Python操作Redis之普通连接和连接池

安装redis模块:

pip install redis

1.redis之普通连接

import redis
# 拿到一个连接,通过连接操作数据
conn = redis.Redis()
conn = redis.Redis(host='localhost', port=6379)
conn.set('name','lqz')
conn.close()

2.redis连接池
redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。
pool.py

import redis

POOL = redis.ConnectionPool(max_connections=10)

redis.py

import redis

# 创建池,池的大小是10,最多放10个连接
# 池需要做成单例,整个项目全局只有一个
# Python 的模块就是天然的单例模式
from pool import POOL

# 从池中获取连接
conn=redis.Redis(connection_pool=POOL)

conn.set('age',14)

conn.close()

redis连接池原理:
创建一个池,池中比如10个连接,池先和redis连接,现在过来1个连接,直接去池里拿,如果过来11个连接,多出来的1个连接必须等待其中1个释放,才可以拿,这样避免了频繁操作redis,导致redis资源暴涨甚至崩溃。

三、Python操作Redis之字符串操作

在这里插入图片描述

# import redis
# conn = redis.Redis()
## 1 set(name, value, ex=None, px=None, nx=False, xx=False)
# ex,过期时间(秒)px,过期时间(毫秒)
# nx,如果设置为True,则只有name不存在时,当前set操作才执行,值存在,就修改不了,执行没效果
# xx,如果设置为True,则只有name存在时,当前set操作才执行,值存在才能修改,值不存在,不会设置新值
# conn.set('hobby', '篮球', ex=8)
# conn.set('name', 'lqz')
# conn.set('name', 'egon', nx=True)
# conn.set('name', 'egon')
# conn.set('name', 'dlrb', xx=True)
# conn.set('name1', 'dlrb', xx=True)

## 2 setnx(name, value)

# conn.setnx('name','ddd')
# conn.setnx('name1','ddd')


## 3 setex(name, time, value)
# conn.setex('age',18,5)

##4 psetex(name, time_ms, value) 以毫秒过期时间
# conn.psetex('xx',3000,'ss')


## 5 mset(*args, **kwargs)  # 批量设置和一次次设置有什么区别?一次网络请求

# conn.mset({'name2':'egon','name3':'lyf'})


## 6 get(name)  # byte格式

# print(conn.get('name2'))

## 7 mget({'k1': 'v1', 'k2': 'v2'})

# res=conn.mget('name1','name2')
# res=conn.mget(['name1','name2'])


# 8 getset(name, value)

# res=conn.getset('name1','ppp')
# print(res)


# 9 getrange(key, start, end)  # 前闭后闭区间,以unicode编码存储,取字节

# res=conn.getrange('name1',0,5)
# print(res.decode('utf-8'))


# 10 setrange(name, offset, value)
# conn.setrange('name1',10,'pppppp')

# 10111111  ---> 112--->p
# 11 setbit(name, offset, value)
# conn.setbit('name1',2,0)

# getbit(name, offset)
# print(conn.getbit('name1',2))


# 12  bitcount(key, start=None, end=None)


# 13 strlen(name)
# print(conn.strlen('name1'))


# 14 incr(self, name, amount=1)  ******  页面访问量
# conn.incr('name1')  # 自增1
# 15 decr(self, name, amount=1)  #自减


# 16 incrbyfloat(self, name, amount=1.0)
# conn.incrbyfloat('name1',1.2)
# print(res)

# conn.close()
# 记住的
'''
get
set
mget
mset
strlen
incr
'''

四、Python操作Redis之hash操作

在这里插入图片描述

# import redis
# conn = redis.Redis()
# 1 hset(name, key, value)
# conn.hset('hash1','name','lqz')
# conn.hset('hash1', 'age', '19')

# 2 hget(name,key)

# print(conn.hget('hash1','age'))

# 3 hmset(name, mapping)  # 弃用了,但是还可以用 批量设置

# conn.hmset('user_1_info', {'name': 'lyf', 'age': 33,'hobby':'篮球'})
# conn.hset('user_2_info', mapping={'name': 'lyf', 'age': 33,'hobby':'篮球'})


# 4 hmget(name, keys, *args) 批量获取
# res=conn.hmget('user_2_info','age','hobby')
# res = conn.hmget('user_2_info', ['age', 'hobby'])
# print(res)

# 两种传值方式
# from redis.client import list_or_args
# conn.hmget('user_2_info','age','hobby')
# res = list_or_args('age', ['hobby', ])

#res = conn.hmget('user_2_info', ['age', 'hobby'])
# res = list_or_args(['age', 'hobby'],[])
# print(res)


# 5 hgetall(name)  获取所有 ,慎用,生产环境中,尽量不要用
# res=conn.hgetall('user_2_info')
# print(res)


# 6 hlen(name)
# res=conn.hlen('user_2_info')
# print(res)


# 7 hkeys(name)
# res=conn.hkeys('user_2_info')
# print(res)


# 8 hvals(name)

# res=conn.hvals('user_2_info')
# print(res)


# 9 hexists(name, key)
# res=conn.hexists('user_2_info','name1')
# print(res)


# 10 hdel(name,*keys)
# res=conn.hdel('user_2_info','name')
# print(res)

# 11 hincrby(name, key, amount=1) age自增1
# conn.hincrby('user_2_info','age')

# 12 hincrbyfloat(name, key, amount=1.0)


# 13 hscan(name, cursor=0, match=None, count=None)  # 不要使用hgetall
# 由于无序,这个方法咱们一般不同,给hscan_iter,从hash中取出一部分值,会以count为基准,但不完全是count
# res=conn.hscan('test_hash',count=11)
# print(len(res[1]))

# 14 hscan_iter(name, match=None, count=None)
# hash 类型本身就无序
# for i in range(1000):
#     conn.hset('test_hash','%s_key'%i,'鸡蛋_%s'%i)

# res=conn.hgetall('test_hash')

# 取出所有数据,跟hgetall比,更节省内存  √√√推荐使用
# for key in conn.hscan_iter('test_hash',count=100):  # 生成器
#     print(key)

# conn.close()
# 记住的
'''
hset
hget
hmset
hmget
hlen
hexists
hincrby
hscan_iter:分批获取数据
'''

五、Python操作Redis之列表操作

在这里插入图片描述

# import redis
# conn = redis.Redis()

# 1  lpush(name,values)  # 从列表的左侧插入值
# conn.lpush('names','lqz','egon')
# conn.lpush('names','lyf','dlrb')
# conn.lpush('names','pyy')

# conn.rpush('names','mrzh')  # 从右侧往里推数据


# 2 lpushx(name,value)  # 只能key存在,才能放进去
# conn.lpushx('names','999')
# conn.lpushx('names1','999') #不存在的放不进去


# 3 llen(name)
# print(conn.llen('names'))


# 4 linsert(name, where, refvalue, value))
# where:before或者after,大小写都可以
# conn.linsert('names','after','egon','fengjie')
# conn.linsert('names','BEFORE','egon','rh')

# 5 r.lset(name, index, value)   #位置从零开始
# conn.lset('names',5,'l_egon')

# r.lrem(name, num,value )  # 删除元素
# conn.lrem('names',0,'lqz')  #把内部所有lqz都移除
# conn.lrem('names',1,'lqz')  #从左往右移除一个符合
# conn.lrem('names', -1, 'lqz')  # 从右往左移除一个符合


# 6 lpop(name)
# conn.lpop('names')   # 从左侧弹出一个
# conn.rpop('names')   # 从右侧弹出一个


# 7 lindex(name, index) # 拿某个位置的值,从0开始
# res=conn.lindex('names',1)
# print(res)


# 8 lrange(name, start, end)
# res=conn.lrange('names',1,conn.llen('names'))  # 获取起始到结束位置的值,前闭后闭
# print(res)


# 9  ltrim(name, start, end) # 修剪
# res=conn.ltrim('names',2,4)  # 只保留2--4之间的,其他全删除


# 10 rpoplpush(src, dst)  # 两个列表
# conn.lpush('names1','xx','yy')
# conn.rpoplpush('names','names1')


# 11 blpop(keys, timeout)    # 阻塞式弹出,有值可以弹,没有值就夯住,直到有值,
# 基于它可以做消息队列,如果是简单的消息队列,就可以使用redis的list类型
# res=conn.blpop('names',4)  # 4为超时时间
# print(res)

# IPC:进程间通信


# 12 brpoplpush(src, dst, timeout=0)
# 一次性把list中值全取出来
# res = conn.lrange('names', 0, conn.llen('names'))

# 自定义增量迭代取值(哪个地方用过生成器)

# conn.lpush('test',*[1,2,3,4,45,5,6,7,7,8,43,5,6,768,89,9,65,4,23,54,6757,8,68])

# def scan_list(name, count=2):
#     index = 0
#     while True:
#         data_list = conn.lrange(name, index, count + index - 1)
#         if not data_list:
#             return
#         index += count
#         for item in data_list:
#             yield item
#
#
# for item in scan_list('test',2):
#     print(item)

# conn.close()
# 记住的
'''
lpush
llen
lrem
lindex
lpop
lrange
'''

六、Python操作Redis之set操作

Set操作,Set集合就是不允许重复的列表

sadd(name,values)

# name对应的集合中添加元素
scard(name)

获取name对应的集合中元素个数
sdiff(keys, *args)

在第一个name对应的集合中且不在其他name对应的集合的元素集合
sdiffstore(dest, keys, *args)

# 获取第一个name对应的集合中且不在其他name对应的集合,再将其新加入到dest对应的集合中
sinter(keys, *args)

# 获取多一个name对应集合的并集
sinterstore(dest, keys, *args)

# 获取多一个name对应集合的并集,再讲其加入到dest对应的集合中
sismember(name, value)

# 检查value是否是name对应的集合的成员
smembers(name)

# 获取name对应的集合的所有成员
smove(src, dst, value)

# 将某个成员从一个集合中移动到另外一个集合
spop(name)

# 从集合的右侧(尾部)移除一个成员,并将其返回
srandmember(name, numbers)

# 从name对应的集合中随机获取 numbers 个元素
srem(name, values)

# 在name对应的集合中删除某些值
srem(name, values)

# 在name对应的集合中删除某些值
sunion(keys, *args)

# 获取多一个name对应的集合的并集
sunionstore(dest,keys, *args)

# 获取多一个name对应的集合的并集,并将结果保存到dest对应的集合中
sscan(name, cursor=0, match=None, count=None)
sscan_iter(name, match=None, count=None)

# 同字符串的操作,用于增量迭代分批获取元素,避免内存消耗太大
有序集合,在集合的基础上,为每元素排序;元素的排序需要根据另外一个值来进行比较,所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。

 zadd(name, *args, **kwargs)

# 在name对应的有序集合中添加元素
# 如:
     # zadd('zz', 'n1', 1, 'n2', 2)
     # 或
     # zadd('zz', n1=11, n2=22)
zcard(name)

# 获取name对应的有序集合元素的数量
zcount(name, min, max)

# 获取name对应的有序集合中分数 在 [min,max] 之间的个数
zincrby(name, value, amount)

# 自增name对应的有序集合的 name 对应的分数
r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)

复制代码
# 按照索引范围获取name对应的有序集合的元素
 
# 参数:
    # name,redis的name
    # start,有序集合索引起始位置(非分数)
    # end,有序集合索引结束位置(非分数)
    # desc,排序规则,默认按照分数从小到大排序
    # withscores,是否获取元素的分数,默认只获取元素的值
    # score_cast_func,对分数进行数据转换的函数
 
# 更多:
    # 从大到小排序
    # zrevrange(name, start, end, withscores=False, score_cast_func=float)
 
    # 按照分数范围获取name对应的有序集合的元素
    # zrangebyscore(name, min, max, start=None, num=None, withscores=False, score_cast_func=float)
    # 从大到小排序
    # zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=float)
复制代码
zrank(name, value)

# 获取某个值在 name对应的有序集合中的排行(从 0 开始)
 
# 更多:
    # zrevrank(name, value),从大到小排序
zrangebylex(name, min, max, start=None, num=None)

复制代码
# 当有序集合的所有成员都具有相同的分值时,有序集合的元素会根据成员的 值 (lexicographical ordering)来进行排序,而这个命令则可以返回给定的有序集合键 key 中, 元素的值介于 min 和 max 之间的成员
# 对集合中的每个成员进行逐个字节的对比(byte-by-byte compare), 并按照从低到高的顺序, 返回排序后的集合成员。 如果两个字符串有一部分内容是相同的话, 那么命令会认为较长的字符串比较短的字符串要大
 
# 参数:
    # name,redis的name
    # min,左区间(值)。 + 表示正无限; - 表示负无限; ( 表示开区间; [ 则表示闭区间
    # min,右区间(值)
    # start,对结果进行分片处理,索引位置
    # num,对结果进行分片处理,索引后面的num个元素
 
# 如:
    # ZADD myzset 0 aa 0 ba 0 ca 0 da 0 ea 0 fa 0 ga
    # r.zrangebylex('myzset', "-", "[ca") 结果为:['aa', 'ba', 'ca']
 
# 更多:
    # 从大到小排序
    # zrevrangebylex(name, max, min, start=None, num=None)
复制代码
zrem(name, values)

# 删除name对应的有序集合中值是values的成员
 
# 如:zrem('zz', ['s1', 's2'])
zremrangebyrank(name, min, max)

# 根据排行范围删除
zremrangebyscore(name, min, max)

# 根据分数范围删除
zremrangebylex(name, min, max)

# 根据值返回删除
zscore(name, value)

# 获取name对应有序集合中 value 对应的分数
zinterstore(dest, keys, aggregate=None)

# 获取两个有序集合的交集,如果遇到相同值不同分数,则按照aggregate进行操作
# aggregate的值为:  SUM  MIN  MAX
zunionstore(dest, keys, aggregate=None)

# 获取两个有序集合的并集,如果遇到相同值不同分数,则按照aggregate进行操作
# aggregate的值为:  SUM  MIN  MAX
zscan(name, cursor=0, match=None, count=None, score_cast_func=float)
zscan_iter(name, match=None, count=None,score_cast_func=float)

# 同字符串相似,相较于字符串新增score_cast_func,用来对分数进行操作

七、Python操作Redis之其他操作(通用操作)

# import redis
# conn=redis.Redis()
# 1 delete(*names)
# # 根据删除redis中的任意数据类型
# conn.delete('test_hash')


# 2 exists(name)
# # 检测redis的name是否存在
# res=conn.exists('names')
# print(res)  # 1 表示存在  0表示不在


# 3 keys(pattern='*')  获取所有的key值,可以过滤
# res=conn.keys(pattern='n*')
# res=conn.keys(pattern='nam?')
# print(res)


# 4 expire(name ,time)
# # 为某个redis的某个name设置超时时间
# conn.expire('names1',9)


#5  rename(src, dst)
# # 对redis的name重命名为
# conn.rename('test','test1')


#6  move(name, db))
# # 将redis的某个值移动到指定的db下
# conn.move('hash1',5)


# 7 randomkey()
# 随机获取一个redis的name(不删除)
# res=conn.randomkey()
# print(res)


# 8 type(name)  查看key的类型  5 大数据类型
# res=conn.type('user_1_info')
# res=conn.type('name1')
# print(res)

# conn.close()

八、管道

redis-py默认在执行每次请求都会创建(连接池申请连接)和断开(归还连接池)一次连接操作,如果想要在一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline 是原子性操作。

# redis是非关系型数据库,不支持事务
# 管道,我们可以通过管道来模拟事务----》要么都成功,要么都失败:一个事务
# import redis
# conn = redis.Redis()

# 创建一个管道
# pipe = conn.pipeline(transaction=True)
# 开启事务
# pipe.multi()

# 向管道中放入命令
# pipe.decrby('egon_money',50)
# raise Exception('ssss')
# pipe.incrby('lqz_money',50)

#让管道中的命令执行
# pipe.execute()

九、Django中使用Redis

1.通用方案
创建pool.py文件:

import redis
POOL = redis.ConnectionPool(max_connections=1000)

在使用的位置添加:

from .pool import POOL
import redis
def test(request):
    conn = redis.Redis(connection_pool=POOL)
    res=conn.get('name')
    print(res)
    return HttpResponse('ok')

2.django方案,第三方模块
下载模块:

pip install django-redis

在配置文件中写:

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {"max_connections": 100}
        }
    }
}

使用的位置:

from django_redis import get_redis_connection
def test(request):
    conn = get_redis_connection()  #从连接池中拿一个连接
    res=conn.get('name')
    print(res)
    return HttpResponse('ok')

一旦使用了它,后续的django缓存,都缓存到redis中

cache.set('name','xxx')

django的缓存很高级,可以缓存python中所有的数据类型,包括对象---->把对象通过pickle序列化成二进制,存到redis的字符串中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/15868.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RocketMq windows 安装

RocketMq安装步骤: 1、直接在官网下载。也可以从这里自取 https://rocketmq.apache.org/download/ 2、修改bin目录下的文件 runserver.cmd 和 runbroker.cmd文件。主要修改所占用内存的大小。 runserver.cmd 修改如下: runbroker.cmd 修改如下&#xff…

【人脸检测】——Sample and Computation Redistribution for Efficient Face Detection论文简读

人脸检测 摘要 在非受控人脸检测方面已经取得了巨大的进步,但低计算成本和高精度的高效人脸检测仍然是一个开放的挑战。作者提出了两种简单而有效的方法:样本再分配(SR)和计算再分配(CR)。在WIDER FACE上进…

AI失业潮来袭,某些部门裁员过半

历史的车轮滚滚向前,每次生产力的大幅跃进,都会造成一批失业潮。想当年,纺纱机的出现让无数手工作坊的织布师傅失业。如今,在AI技术的催化下,同样的事正在互联网行业的各个领域重演。 疯狂的裁员浪潮 “AI15秒做的&am…

np.convolve(x,h, mode=‘##‘)的使用

用法: np.convolve(a,v,mode) a代表卷积数据,v卷积核大小,mode卷积方式,mode卷积方式有三种 same full valid mode可能的三种取值情况: full’ 默认值,返回每一个卷积值,长度是NM-1,在卷积的…

【策略设计模式详解】C/Java/JS/Go/Python/TS不同语言实现

简介 策略模式(Strategy Pattern)属于行为型设计模式。将每一个算法封装到具有共同接口的独立类中,根据需要来绑定策略,使得具体实现和策略解耦。 当你想使用对象中各种不同的算法变体,使用if...else 所带来的复杂和…

Python入门教程+项目实战-11.5节: 程序实战-选择排序算法

目录 11.5.1 排序算法简介 11.5.2 选择排序算法 11.5.3 系统学习python 11.5.1 排序算法简介 所谓排序,是指将数据集合中的元素按从小到大的顺序进行排列,或按从大到小的顺序进行排列。前者称为升序排序,后者称为降序排序。在数据结构与算…

【Java笔试强训 7】

🎉🎉🎉点进来你就是我的人了博主主页:🙈🙈🙈戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔🤺🤺🤺 目录 一、选择题 二、编程题 🔥Fibona…

( 哈希表) 594. 最长和谐子序列 ——【Leetcode每日一题】

❓594. 最长和谐子序列 难度:简单 和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是 1 。 现在,给你一个整数数组 nums ,请你在所有可能的子序列中找到最长的和谐子序列的长度。 数组的子序列是一个由数组派生出来的序列&am…

AWSFireLens轻松实现容器日志处理

applog应用程序和fluent-bit共享磁盘,日志内容是json格式数据,输出到S3也是JSON格式 applog应用部分在applog目录: Dockerfile文件内容 FROM alpine RUN mkdir -p /data/logs/ COPY testlog.sh /bin/ RUN chmod 777 /bin/testlog.sh ENTRYP…

MySQL知识学习01

1、什么是关系型数据库? 顾名思义,关系型数据库(RDBMS,Relational Database Management System)就是一种建立在关系模型的基础上的数据库。关系模型表明了数据库中所存储的数据之间的联系(一对一、一对多、多对多&am…

宏基因组组装 | 就现在!做出改变!!

微生态研究的核心难点是什么! 基因组组装! 从宏基因组数据中组装获得细菌的完整基因组(complete MAGs)是微生物组研究的长期目标,但基于NGS的宏基因组测序和组装方法是无法实现完整的细菌基因组组装的。即便是红极一…

【五一创作】Apollo(入门)

Apollo(入门) Quick Start 配置中心是一种统一管理各种应用配置的基础服务组件 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且…

使用pands.rolling方法实现移动窗口的聚合计算

一个问题举例 假设有一个5天的收益数据,需要每3天求出一次平均值来达成某个需求: daterevenue2023-05-01102023-05-02202023-05-03302023-05-04402023-05-0550 1号、2号和3号的数据求一次平均值,2号、3号和4号的数据求一次平均值&#xff…

5.4.1树的存储结构 5.4.2树和森林的遍历

回忆一下树的逻辑结构: 双亲表示法(顺序存储) 如果增加一个结点M,L。毋须按照逻辑上的次序存储。 如果是删除元素: 方案一:比如说删除元素为G,设置其双亲结点为-1。 方案二: 把尾部的结点提上…

Sybase使用sp_helptext查看系统存储过程的源码

sp_helptext存储过程用于显示已编译对象的源代码。 sp_helptext是Sybase ASE内置的存储过程,可从任何位置调用。 但实际上,如果直接使用,常常会得到(令人头大的)错误提示: Msg 17461 Object does not exi…

基于JavaSpringboot+vue国风汉服文化交流宣传系统

基于JavaSpringbootvue国风汉服文化交流宣传系统 博主介绍:5年java开发经验,专注Java开发、定制、远程、指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 文章目…

【可解释AI】图神经网络的可解释性方法及GNNexplainer代码示例

图神经网络的可解释性方法及GNNexplainer代码示例 GNNExplainerIntroductionModelSingle-instance explanations(Explanation via Structural Information)Joint learning of graph structural and node feature information(Explanation via…

SuperMap iClient3D for Cesium 构建隧道

作者:kele 背景 前段时间看到一篇构建隧道的文章(https://blog.csdn.net/supermapsupport/article/details/128453116),突然想到一个使用场景:隧道通常是建在山体下面,是否可以通过这种方式构建出一条贯穿…

使用Python和机器学习进行文本情感分类

使用Python和机器学习进行文本情感分类 1. 效果图2. 原理3. 源码参考这篇博客将介绍如何使用Python进行机器学习的文本情感分类(Text Emotions Classification)。 1. 效果图 训练文本及情感分类前5条数据如下: 训练过程及测试文本情感分类效果图如下: 可以看到 对文本“S…

【量化交易笔记】5.SMA,EMA 和WMA区别

股票中的SMA,EMA和WMA是常用的技术分析指标。这些指标基于历史股价计算得出,可以帮助投资者了解股票的趋势,为决策提供依据。虽然它们都是平均值算法,但它们之间还是有一些区别的。 SMA 简单移动平均线(Simple Moving…