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

news2024/11/26 10:32:55

一、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的字符串中。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【前端知识】Cookie, Session,Token和JWT的发展及区别(上)

【前端知识】Cookie, Session,Token和JWT的发展及区别(上) 1. 背景2. Cookie2.1 Cookie的定义2.2 Cookie的特点2.3 Cookie的一些重要属性✨2.3.1 Cookie的重要属性🎇2.3.2 Cookie的有效期,max-age和作用域,…

SQL注入(一)联合查询 报错注入

目录 1.sql注入漏洞是什么 2.联合查询: 2.1注入思想 2.2 了解information_schema 数据库及表 3.可替代information_schema的表 3.1 sys库中重要的表 4. 无列名注入 利用 join-using 注列名。 4. 报错注入 4.1 常用函数:updatexml、extractvalue…

Java 基础进阶篇(五)—— 接口详解

文章目录 一、接口概述二、接口的基本使用三、接口从 JDK 8 开始新增的方法四、接口的注意事项(了解)补充:接口与接口的关系 一、接口概述 规范的基本特征是约束和公开。 接口就是一种规范,其约束别人必须干什么事情。 所以&…

FileZilla读取目录列表失败(vsftpd被动模式passive mode部署不正确)

文章目录 现象问题原因解决方法临时解决(将默认连接方式改成主动模式)从根本解决(正确部署vsftpd的被动模式) 现象 用FileZilla快速连接vsftpd服务器时,提示读取目录列表失败 问题原因 是我vsftpd服务端的被动模式没…

Python每日一练(20230501)

目录 1. 对链表进行插入排序 🌟🌟 2. 平衡二叉树 🌟🌟 3. 找出素数对 ※ 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 对链表进行…

Linux主机信息搜集

1、系统架构 打印系统信息 uname -a 文件 /etc/issue是一个文本文件,其中包含要在登录提示之前打印的消息或系统标识 cat /etc/issue /etc/lsb-release,/etc/redhat-release文件包含一个被解析以获取信息的描述行 cat /etc/*-release /proc/versi…

创作纪念日让 AI 与我共同记录下今天 — 【第五周年、1460天】

今天正是五一,收到一条消息? 五一还要我加班 😏? 喔,原来是 CSDN 给我发的消息呀!我在 CSDN 不知不觉已经开启第五周年啦! 目录 1.机缘2.收获3.日常4.我与 AI 的“合作”part Ipart II Super al…

java 多用户即时通信系统的实现 万字详解

目录 前言 一、拾枝杂谈 1.项目开发大体流程 : 2.多用户即时通信系统分析 : 1 需求分析 2 整体分析 二、用户登录 1.准备工作 : 2.客户端 : 1 菜单界面 2 登录验证 3 线程创建 4 线程管理 3.服务端 : 1 用户验证 2 线程创建 3 线程管理 4.登录测试 : 三、在线列表 1.…

探索深度学习世界:掌握PyTorch,成为AI领域的行家

探索深度学习世界:掌握PyTorch,成为AI领域的行家 PyTorch的背景介绍PyTorch的基本概念与特点PyTorch的基本应用张量和自动求导神经网络搭建训练和测试模型 模型的保存和加载模型保存:模型加载:模型使用: PyTorch与其他…

【KVM虚拟化】· 命令行KVM安装linux

目录 🍁基础本环境配置 🍁添加lvm卷 🍁qemu-img创建磁盘文件 🍂创建raw格式 🍂创建虚拟机 🍂转换格式为qcow2 🍁virt-install命令参数 🍁案例操作 🦐博客主页&#xff1a…

【C++】 小项目---宠物小屋的分析设计与开发实现

目录 需求 分析设计 动物类 笼子类 房子类 人类 小贴士 整体设计图 开发实现 动物类 笼子类 房子类 人类 小贴士 控制台主函数 需求 动物猫(CCat)、狗(CDog)、蛇(CSnake),包含名字&…

对折纸张厚度超过珠峰

对折 0.1 毫米的纸张,循环对折,超过珠峰高度输出对折次数。 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖免费“圣经”教程《 python 完全自学教程》,不仅仅是基础那么简单…… 地址&a…

【计算机网络】学习笔记:第六章 应用层【王道考研】

基于本人观看学习b站王道计算机网络课程所做的笔记&#xff0c;不作任何获利 仅进行交流分享 特此鸣谢王道考研 若有侵权请联系&#xff0c;立删 如果本篇笔记帮助到了你&#xff0c;还请点赞 关注 支持一下 ♡>&#x16966;<)!! 主页专栏有更多&#xff0c;如有疑问欢迎…

每天一道算法练习题--Day17 第一章 --算法专题 --- ----------布隆过滤器

场景 假设你现在要处理这样一个问题&#xff0c;你有一个网站并且拥有很多访客&#xff0c;每当有用户访问时&#xff0c;你想知道这个 ip 是不是第一次访问你的网站。 hashtable 可以么 一个显而易见的答案是将所有的 IP 用 hashtable 存起来&#xff0c;每次访问都去 hash…

ARM架构基本理论(1)

ARM架构基本理论 一、ARM的简介 ARM&#xff08;Advanced RISC Machine&#xff09;是一种基于RISC&#xff08;Reduced Instruction Set Computing&#xff09;架构的计算机处理器架构&#xff0c;由ARM Holdings&#xff08;ARM公司&#xff09;开发和授权给其他公司生产和…

【C++开发】基于QT+sqlite3的医疗管理系统

文章目录 前言数据库设计主要实现的功能病人列表页面病人信息页信息录入页面信息修改页面 & 信息查看页面 总结 前言 本次做的这个项目是医疗管理系统&#xff0c;是根据需求所定制的&#xff0c;因此只面向个人本地的使用。 本项目是本人在完全0基础的情况下边学边…

14-2-进程间通信-FIFO

一、命名管道FIFO 1.作用范围 对于命名管道FIFO&#xff0c;它可以在不相关的进程间也能相互通信。 2.命名管道可左右用于不相关进程的原因 因为命令管道&#xff0c;提前创建了一个类型为管道的设备文件&#xff0c;在进程里只要使用这个设备文件&#xff0c;就可以相互通信…

14-1-进程间通信-pipe

一.无名管道pipe 特点&#xff1a; (1)半双工&#xff08;在同一时刻&#xff0c;数据传输的方向只能是接收或发送&#xff09;&#xff1b; 例如&#xff1a;对于主机和从机而言&#xff0c;在某一时刻&#xff0c;只能是主机发送&#xff08;从机接收&#xff09;&#xff0…

CentOS+nginx手动搭建WordPress

文章目录 前提条件php安装安装 EPEL 源及源管理工具&#xff1a;安装 REMI 源&#xff1a;安装 PHP7.3 及扩展&#xff1a;设置开机自动启动其他php命令 wordpress 安装下载WordPress将下载的WordPress移动至网站根目录修改WordPress配置文件配置nginx 创建完成后根据域名访问 …

分析linux中动态库so文件的常用方法

前言 在linux系统中&#xff0c;我们经常会遇到各种各样的动态库文件&#xff0c;常见的是.so后缀&#xff0c;那么我们应该如何分析这些文件的用途和作用呢&#xff1f;毕竟我们不能一知半解的“搞事情”。 正文 查看文件属性 首先&#xff0c;我们从整体上了解一下该文件的基…