Redis基础

Redis

简介

Redis是一个key - value存储系统,非关系型数据库(nosql数据库),缓存数据库,数据存在于内存中

Redis支持五大数据类型

  • 字符串
  • 列表
  • hash(字典)
  • 集合
  • 有序集合

使用Redis的好处

  • 速度快:缓存数据库
  • 支持丰富数据类型(五大数据类型)
  • 支持事务(通过管道支持)(单实例上有效)
  • 丰富的特性:可用于缓存、消息队列、按key设置过期时间,过期后自动删除

Redis对比memcached

  • 都是内存数据库
  • Redis类型丰富(五大数据类型),memcached只支持字符串类型
  • Redis支持持久化,memcached不支持持久化
  • Redis速度比memcached块

Redis特点

  • 可以持久化
  • 单线程,单进程
    • Redis最新版本是6.x
    • 6.x版本之前是单线程,单进程

Redis单线程为什么这么快(官方:10w左右并发,实际:6w左右并发)

  • 纯内存操作
  • 使用了io多路复用模型(epoll、select)
  • 因为是单线程,不存在线程间切换,节省资源

服务:客户端,服务端(跟MySQL一样,是存数据的地方)

安装

启动Redis服务

  • 在任意路径下敲(前提:已经添加环境变量):redis-server
  • Windows平台已经做成服务,直接开启服务

客户端连接

  • 任意路径下敲:redis-cli -h 127.0.0.1 -p 6379
  • 使用客户端连接
  • 使用python操作(pip install redis)

普通连接与连接池

普通连接

# redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py

import redis

conn = redis.Redis(host='127.0.0.1', port=6379)
conn.set('foo', 'Bar')
print(r.get('foo'))

连接池

# redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销

# 默认:每个Redis实例都会维护一个自己的连接池

# 可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池

import redis

pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
conn = redis.Redis(connection_pool=pool)
conn.set('foo', 'Bar')
print(r.get('foo'))

把POOL以单例形式使用

# pool.py

import redis

# 拿到一个连接数为3的连接池
# 把POOL做成单例:把它以模块导入方式
POOL=redis.ConnectionPool(max_connections=3,host='127.0.0.1', port=6380)

========================================================================================

import redis

from pool import POOL  # 以模块形式导入,是天然单例
conn=redis.Redis(connection_pool=POOL)
# conn2=redis.Redis(connection_pool=POOL)
# conn3=redis.Redis(connection_pool=POOL)
# conn4=redis.Redis(connection_pool=POOL)
# conn5=redis.Redis(connection_pool=POOL)
# conn6=redis.Redis(connection_pool=POOL)

conn.set('age',19)
conn.close()  # 不是关闭连接,把该连接,放回到连接池

Redis五大数据类型之字符串

字符串操作,Redis中的字符串再内存中按照一个name对应一个value来存储

img

'''
set(name, value, ex=None, px=None, nx=False, xx=False) 重点
setnx(name, value)
setex(name, value, time)
psetex(name, time_ms, value)
mset(*args, **kwargs) 重点
get(name) 重点
mget(keys, *args) 重点
getset(name, value)
getrange(key, start, end)
setrange(name, offset, value)
setbit(name, offset, value)
getbit(name, offset)
bitcount(key, start=None, end=None)

strlen(name) 重点
incr(self, name, amount=1) 重点
incrbyfloat(self, name, amount=1.0)
decr(self, name, amount=1)
append(key, value)
'''


import redis

conn=redis.Redis()

# set:放字符串值
'''
ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为True,则只有name不存在时,当前set操作才执行,值存在,就修改不了,执行没效果
xx,如果设置为True,则只有name存在时,当前set操作才执行,值存在才能修改,值不存在,不会设置新值
'''
# conn.set('name','lqz')
# res=conn.set('name','lqz',ex=3)
# res=conn.set('name','lqz',px=3000)
# res=conn.set('name','lqz')
# res=conn.set('name','egon')
# res=conn.set('name','lqz',nx=True)
# res=conn.set('name','19',xx=True)


# get 获取值
# res=conn.get('name')

# mset 批量设置值

# conn.mset({'name':'lqz','age':19,'sex':'男'})

# mget  批量获取值
# res=conn.mget(['name','age'])
# res=conn.mget('name','age')

# conn.setex(name, value, time)
# conn.psetex(name, time_ms, value)
# conn.set(name, valeu, px=time)

# res=conn.getset('name', '刘亦菲')


# res=conn.getrange('name',3,5)  #前闭后闭区间  拿到 亦 这个字   拿字节
#
# print(str(res,encoding='utf-8'))


# res=conn.setrange('name',0,'lqzzzzzzz')
# res=conn.setrange('name',0,'qq')


##获取和设置比特位
# setbit(name, offset, value)
# getbit(name, offset)


# print(conn.getbit('name',3))
# conn.setbit('name',0,1)
# print(conn.getbit('name',0))

# print(conn.strlen('name'))  # 指的是字节     获取字节长度

# conn.incr('age')   # 让该键自增1
# conn.incrby('age',3)   # 让该键自增3
# conn.incrbyfloat('age', amount=1.1)


conn.append('name', 'nb')

conn.close()

Redis五大数据类型之hash

img

'''
hset(name, key, value)   重点
hmset(name, mapping)   重点
hget(name,key)        重点
hmget(name, keys, *args)  重点
hgetall(name)
hlen(name)              重点
hkeys(name)
hvals(name)
hexists(name, key)
hdel(name,*keys)
hincrby(name, key, amount=1)   重点
hincrbyfloat(name, key, amount=1.0)
hscan(name, cursor=0, match=None, count=None)
hscan_iter(name, match=None, count=None)
'''

import redis

conn=redis.Redis()

# conn.hset('users','name','egon')
# conn.hset('users','age','19')

# res=conn.hget('users','age')
# res=conn.hget('users','name')



# conn.hmset('h1',{'name':'lqz','age':19})


# res=conn.hmget('h1',['name','age'])
# res=conn.hmget('h1','name','age')


# res=conn.hlen('users')  # 统计键值对的个数



# res=conn.hkeys('users')
# res=conn.hvals('users')
# hvals(name)
# print(str(res[2],encoding='utf-8'))


# res=conn.hexists('users','age1')
# res=conn.hdel('users','age')



# conn.hincrby('h1', 'age',7)
# conn.hincrbyfloat('h1', 'age', amount=-1.01)



# for i in range(1000):
#     conn.hset('htest',i,'第%s个鸡蛋'%i)

###hash(字典)类型是无序的

# res=conn.hgetall('htest')
# print(res)



# res=conn.hscan('htest', cursor=0,count=500)  # 用的少
# print(res)
# res=conn.hscan('htest', cursor=254,count=499)  # 用的少
# print(res)
# res=conn.hscan('htest', cursor=511,count=2)  # 用的少
# print(res)
# print(res)
# print(len(res[1]))


res=conn.hscan_iter('htest', count=20)   # 把hash类型的所有数据都打印出来,比hgetall节省内存
for item in res:
    print(str(item[1],encoding='utf-8'))

# print(res)



conn.close()

Redis五大数据类型之列表

img

'''

lpush(name,values)   #从左侧插入值
lpushx(name,value)
llen(name)           # 重点
linsert(name, where, refvalue, value))  # 重点
lset(name, index, value)
lrem(name, value, num)        # 删除值
lpop(name)             #从左侧弹出
lindex(name, index)
lrange(name, start, end)
ltrim(name, start, end)
rpoplpush(src, dst)
blpop(keys, timeout)          # 阻塞式弹出
brpoplpush(src, dst, timeout=0)
'''

import redis

conn=redis.Redis()

# conn.lpush('list1','1')  #左侧插入,上部
# conn.lpush('list1','lqz')
# conn.rpush('list1','egon')  #右侧插入,下部

# conn.rpushx('list1','刘亦菲')  # 只有name存在才能插入
# conn.lpushx('list2','刘亦菲')


# print(conn.llen('list1'))


# conn.linsert('list1','before','egon','迪丽热巴')

# conn.linsert('list1','AFTER','egon','古力娜扎')
# conn.linsert('list1','AFTER','1','99999')


# conn.lset('list1',3,66666) # 修改某个位置的值



# 如果count=0,表示删除所有符合条件的,删除所有66666
# conn.lrem('list1',0,'66666')

# 如果count=1,表示从左侧删除1个符合条件的,删除1个99999
# conn.lrem('list1',1,'99999')
# 如果count=-2,表示从底部,从右侧,删除符合条件的2个
# conn.lrem('list1',-2,'99999')



# res=conn.lpop('list1')
# res=conn.rpop('list1')


# res=conn.lindex('list1',1)  #返回某个索引的值  列表操作 l[0]


# res=conn.lrange('list1', 0, 4)  # 前闭后闭


# res=conn.ltrim('list1', 1, 3)  #修剪,不符合范围的都删除,前闭后闭
# conn.lpush('list2','李易峰','刘亦菲','迪丽热巴')

# conn.rpoplpush('list1', 'list2')

res=conn.blpop('list2',timeout=2)          # 阻塞式弹出,通过它做一些分布式任务,可以用来做消息队列
print(res)


# brpoplpush(src, dst, timeout=0)




conn.close()

其他通用操作

'''

delete(*names)
# 根据删除redis中的任意数据类型

exists(name)
# 检测redis的name是否存在

keys(pattern='*')
# 根据模型获取redis的name

expire(name ,time)
# 为某个redis的某个name设置超时时间

rename(src, dst)
# 对redis的name重命名为

move(name, db))
# 将redis的某个值移动到指定的db下

randomkey()
# 随机获取一个redis的name(不删除)

type(name)
#查看类型
'''



##通用操作

import redis

conn=redis.Redis()
# conn.delete('h1')


# print(conn.exists('name'))


# res=conn.keys('list*')
# print(res)

# conn.expire('list1',3)

# conn.rename('sex','sex111')

# conn.move('sex111',2)


# res=conn.randomkey()

# res=conn.type('users')
res=conn.type('name')

print(res)
conn.close()

管道

# redis支持事务,借助于管道


# import redis
#
#
# conn=redis.Redis()
#
# conn.decr('zhangsan',100)
#
# raise Exception('程序废了,出异常了')
#
# conn.incrby('wo',100)
#
# conn.close()


# 借助于管道实现

import redis
conn=redis.Redis()
pip_line=conn.pipeline(transaction=True)  # 开启一个管道
pip_line.decr('zhangsan',100)            # 往管道中放一个命令
raise Exception('程序崩了')
pip_line.incrby('wo',100)                # 往管道中放一个命令

pip_line.execute()                       # 把管道中的命令一次性执行

conn.close()

Django使用Redis

# 第一种:通用方式(任何web框架都可以)
	新建一个文件,其他文件导入使用

# 第二种:django提供的
	-在配置文件中配置
    	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}  # 连接池大小为100
                    # "PASSWORD": "123",
                }
            }
        }
    -安装django_redis模块
    -使用
    from django_redis import get_redis_connection
    def index(request):
        conn=get_redis_connection()
        res=conn.get('name')
        print(res)
        return HttpResponse('okkkkk')
    
   -一旦这样配置,django中的缓存,也用redis
	cache.set('key',python的任意对象)
posted @ 2021-07-29 08:00  Jerry`  阅读(47)  评论(0编辑  收藏  举报