Redis简单介绍

4 篇文章 0 订阅
3 篇文章 0 订阅

目录

 Redis介绍

 redis 为什么这么快

redis 应用场景(了解)

下载安装

​编辑    win版本下载地址

redis服务    

pycharm 操作redis

 redis连接池

​编辑使用连接池链接

redis 数据库

 字符串

 hash 

列表操作

redis管道

redis其他操作

django中集成redis

方式一: 直接使用

方式二: 使用第三方模块django-redis

下载模块:

方式三: 借助于django的缓存使用redis

 Redis介绍

redis是一款非关系型的nosql数据库【存数据的地方,使用内存存储,速度非常快, 可以持久化存储数据数据【从内存同步到硬盘】。 

数据类型丰富【5大数据类型:字符串,列表,哈希(字典),集合,有序集合】,以key-value形式存储【根本没有表的结构,相当于咱们的字典】
    
    -nosql:指非关系型数据库:1 不限于SQL  2 没有sql
    


 redis 为什么这么快

    -1 高性能的网络模型:IO多路复用的epoll模型,承载住非常高的并发量
    -2 纯内存操作,避免了很多io
    -3 单线程架构,避免了线程间切换的消耗
        -6.x之前:单线程,单进程
        -6.x以后,多线程架构,数据操作还是使用单线程,别的线程做数据持久化,其他操作

redis 应用场景(了解)


    1 当缓存数据库使用,接口缓存,提高接口响应速度
        -请求进到视图---》去数据查询[多表查询,去硬盘取数据:速度慢]----》转成json格式字符串---》返回给前端
        -请求进到视图---》去redis[内存]----》取json格式字符串---》返回给前端
    2 做计数器:单线程,不存在并发安全问题
        -统计网站访问量
        -个人站点浏览量
        -文章阅读量
        
    3 去重操作:集合
    4 排行榜:有序集合
        -阅读排行榜
        -游戏金币排行榜
        
    5 布隆过滤器
    6 抽奖
    7 消息队列

下载安装

redis是一款开源软件:使用c语言写的---【编译型语言,在操作系统运行,要编译成可执行文件,由于采用了IO多路复用的epoll模型,所以它不支持windows,只有linux操作系统支持epoll】

微软官方:改了,编译成可执行的安装包,下载一路下一步安装
    -版本没有最新

官网:https://redis.io/
    -下载完是源代码:c语言源码 :

https://redis.io/download/#redis-stack-downloads

    -最稳定:6.x
    -最新7.x

中文网:

http://redis.cn/download.html


    -上面最新只到5.x
    


    
win版本下载地址


   最新5.x版本 https://github.com/tporadowski/redis/releases/
   最新3.x版本 https://github.com/microsoftarchive/redis/releases
    下载完一路下一步即可,具体可参照:https://www.cnblogs.com/liuqingzheng/p/9831331.html
    

redis服务
    

win装完会有redis服务
    -启动服务,手动停止
    -客户端链接:

redis-cli -h 127.0.0.1 -p 6379

 -简单命令:

    set name yietong
        get name
        ping

       
    -停掉服务:
        -去win服务点关闭
        -客户端关闭:

shutdown

 

     redis本质也是cs架构的软件
redis 服务器端
redis 客户端 
    -redis-cli
    -图形化工具:redis-desktop-manager
    -python操作
    

pycharm 操作redis

安装包

pip3 install redis
from redis import Redis

conn=Redis( host="localhost",port=6379)
# conn.set('name','yietong')
print(conn.get('name'))
conn.close()

 redis连接池

POOL.py

import redis

pool = redis.ConnectionPool(max_connections=200, host='127.0.0.1', port=6379)

redis-pool-demo.py

# 直接连接
from redis import Redis
from threading import Thread

# 直接链接
def get_name_from_redis():
    conn = Redis(host="localhost", port=6379)
    print(conn.get('name'))
    conn.close()

for i in range(100):
    t=Thread(target=get_name_from_redis)
    t.start()

import time
time.sleep(10)


使用连接池链接

import redis
from POOL import pool
def get_name_from_redis():
    # 创建一个连接池,保证它是单例,全局只有一个pool对象:使用模块导入方式实现单例

 

    conn = redis.Redis(connection_pool=pool) #m每执行一次会从池中取一个链接,如果没有,等待
    res=conn.get('name')
    print(res)
    conn.close()


for i in range(100):
    t=Thread(target=get_name_from_redis)
    t.start()


import time
time.sleep(10)

redis 数据库

Redis 支持的数据类型概述

Redis 是一个数据结构服务器。 Redis 的核心是提供一系列本机数据类型,可帮助您解决从缓存到队列再到事件处理的各种问题。

 字符串


Redis 字符串是最基本的 Redis数据类型,表示字节序列。

# 字符串
1 set(name, value, ex=None, px=None, nx=False, xx=False)
2 setnx(name, value)
3 psetex(name, time_ms, value)
4 mset(*args, **kwargs)
4 get(name)
5 mget(keys, *args)
6 getset(name, value)
7 getrange(key, start, end)
8 setrange(name, offset, value)
9 setbit(name, offset, value)
10 getbit(name, offset)
11 bitcount(key, start=None, end=None)
12 strlen(name)
13 incr(self, name, amount=1)
14 incrbyfloat(self, name, amount=1.0)
15 decr(self, name, amount=1)
16 append(key, value)
##   记住的:get set strlen

set()

def set(
    self,
    name: KeyT,
    value: EncodableT,
    ex: Union[ExpiryT, None] = None,  # 过期时间(秒)
    px: Union[ExpiryT, None] = None,  # 过期时间(毫秒)
    nx: bool = False,  # 如果设置为True,则只有name不存在时,当前set操作才执行,值存在,就修改不了,执行没效果。
    xx: bool = False,  # 如果设置为True,则只有name存在时,当前set操作才执行,值存在才能修改,值不存在,不会设置新值。
    keepttl: bool = False,  # 如果为True,保留与该键关联的生存时间。
    get: bool = False,  # 如果为True,将键name处的值设置为value并返回旧值存储在key中,如果key不存在则为None。
    exat: Union[AbsExpiryT, None] = None,  # 设置指定的Unix时间,该键将在该时间到期,单位为秒。
    pxat: Union[AbsExpiryT, None] = None,  # 设置指定的Unix时间,该键将在该时间到期,单位为毫秒。
import redis

conn = redis.Redis()
conn.set('name', 'yietong')
conn.set('age', 22)

conn.close()

setnx()

# 相当于set(..., nx=True)
def setnx(self, name: KeyT, value: EncodableT) -> ResponseT:

conn.setnx('name','xxx')  # 存在不修改,执行没效果
conn.setnx('hobby','pingpang')

psetex()

# 本质就是 set(..., px)设置时间(毫秒)
def psetex(self, name: KeyT, time_ms: ExpiryT, value: EncodableT):

conn.psetex('name', 3000, 'yietong')

mset()

# 批量设置
def mset(self, mapping: Mapping[AnyKeyT, EncodableT]) -> ResponseT:
conn.mset({'name': 'yietong', 'age': 22, 'xxx': 'yyy'})

get()

def get(self, name: KeyT) -> ResponseT:
# 获取值,取到是bytes格式
# 可以在实例化redis对象时指定参数decode_responses=True
res = conn.get('name')
print(res)  # b'yietong'

mget()

# 批量获取
def mget(self, keys: KeysT, *args: EncodableT) -> ResponseT:

res = conn.mget('name', 'age')
print(res)  # [ b'yietong', b'22']

getset()

# 先获取在设置
def getset(self, name: KeyT, value: EncodableT) -> ResponseT:
res = conn.getset('age', 30)
print(res)  # b'22'

getrange()

# 取的是字节,左闭右闭区间。
def getrange(self, key: KeyT, start: int, end: int) -> ResponseT:

res = conn.getrange('name',0,3)
print(res)  # b'yietong'

setrange()

'''
从offset开始重新设置值,如果``offset``加上``value``的长度超过原始值的长
度,新值将比以前大。如果``offset``超过了原始值的长度,则用null填充。
'''
def setrange(self, name: KeyT, offset: int, value: EncodableT) -> ResponseT:
res = conn.setrange('name',10, 'goodmorning')
print(res)  # 22

setbit()

# 设置或清除存储在键的字符串值中的偏移位。
# 根据值设置或清除位,该值可以是 0 或 1.
def setbit(self, name: KeyT, offset: int, value: int) -> ResponseT:

bitcount()

# 返回` ' key ' `的值中设置的位数。可选``start``和``end``参数表示要考虑哪些字节
def bitcount(
    self,
    key: KeyT,
    start: Union[int, None] = None,
    end: Union[int, None] = None,
    mode: Optional[str] = None,
) -> ResponseT

res = conn.bitcount('hobby', 0, 6)
print(res)  # 28

strlen()

# 返回` ' name ' `的值中存储的字节数
def strlen(self, name: KeyT) -> ResponseT:
print(conn.strlen('hobby'))  # 8

incr()

def incr(self, name: _Key, amount: int = ...) -> int: ...
res = conn.incr('age', amount=2)
print(res)

incrbyfloat()

def incrbyfloat(self, name: KeyT, amount: float = 1.0) -> ResponseT:

decr()

def decr(self, name, amount: int = ...) -> int: ...
print(conn.decr('age'))

append()
将字符串’ ’ value ’ ‘附加到' key '的值上。如果“键”,不存在value创建它。返回值’ ’ key ’ '的新长度。

def append(self, key: KeyT, value: EncodableT) -> ResponseT:
print(conn.append('name', 'hahaha'))  # 14

 hash 

'''
1 hset(name, key, value)
2 hmset(name, mapping)
3 hget(name,key)
4 hmget(name, keys, *args)
5 hgetall(name)
6 hlen(name)
7 hkeys(name)
8 hvals(name)
9 hexists(name, key)
10 hdel(name,*keys)
11 hincrby(name, key, amount=1)
12 hincrbyfloat(name, key, amount=1.0)
13 hscan(name, cursor=0, match=None, count=None)
14 hscan_iter(name, match=None, count=None)
'''

##   记住:hset hget  hexists hincrby hlen


hset() 

'''
在hash `name`中设置`key`为`value`,
``mapping``接受一个由键值对组成的字典
添加到hash ``name``中。
``items``接受一个键值对列表作为参数
添加到hash ``name``中。
返回添加的字段数。
'''
def hset(
     self,
     name: str,
     key: Optional[str] = None,
     value: Optional[str] = None,
     mapping: Optional[dict] = None,
     items: Optional[list] = None,
 ) -> Union[Awaitable[int], int]:
res = conn.hset('info', 'name', 'yietong', mapping={'age': 12, 'xx': 'yy'})
print(res)  # 3

hmset()
将key设置为对应哈希name中的值,mapping字典中的键和值。

def hmset(self, name: str, mapping: dict) -> Union[Awaitable[str], str]:
res = conn.hmset('info',{'xx':'xx', 'yy':'yy'})
print(res)
#  DeprecationWarning: Redis.hmset() is deprecated. Use Redis.hset() instead.
#  res = conn.hmset('info',{'xx':'xx', 'yy':'yy'})
# 已被弃用,使用hset()即可。

hget()

返回哈希值key中的值name

def hget(
    self, name: str, key: str
) -> Union[Awaitable[Optional[str]], Optional[str]]:


res = conn.hget('info', 'xx')
print(res)  # b'xx'

hmget()

返回与keys顺序相同的值的列表。

def hmget(self, name: str, keys: List, *args: List) -> Union[Awaitable[List], List]:

res = conn.hmget('info', ('xx', 'yy'))
print(res)  # [b'xx', b'yy']

hgetall()

返回一个Python字典,由散列的名称/值对组成

def hgetall(self, name: str) -> Union[Awaitable[dict], dict]:

res = conn.hgetall('info')
print(res)  # {b'name': b'yietong', b'age': b'22', b'xx': b'xx', b'yy': b'yy'}

hlen()

返回哈希值name中的元素个数

def hlen(self, name: str) -> Union[Awaitable[int], int]:
res = conn.hlen('info')
print(res)  # 4

hkeys()

返回hash name 中的键列表

def hkeys(self, name: str) -> Union[Awaitable[List], List]:
res = conn.hkeys('info')
print(res)  # [b'name', b'age', b'xx', b'yy']

hvals()

返回hash name中的值列表

def hvals(self, name: str) -> Union[Awaitable[List], List]:
res = conn.hvals('info')
print(res)  # [b'yietong', b'18', b'xx', b'yy']

hexists()

返回一个布尔值,表示key是否存在于哈希name中。

def hexists(self, name: str, key: str) -> Union[Awaitable[bool], bool]:
res = conn.hexists('info','xx')
print(res)  # True

hdel()

从hash name中删除keys

def hdel(self, name: str, *keys: List) -> Union[Awaitable[int], int]:
res = conn.hdel('info','xx', 'yy')
print(res)  # 2

hincrby()

将hash name中的key的值增加amount

def hincrby(
    self, name: str, key: str, amount: int = 1
) -> Union[Awaitable[int], int]:
conn.hset('ingo','age',18)
res = conn.hincrby('info','age',2)
print(res)  # 20

hincrbyfloat()

将hash name中的key的值增加amount

def hincrby(
    self, name: str, key: str, amount: int = 1
) -> Union[Awaitable[int], int]:

hscan()

在哈希表中递增地返回键值对切片,同样返回一个游标。
表示扫描位置。
match允许按模式过滤键
count允许提示最小返回次数

def hscan(
    self,
    name: KeyT,
    cursor: int = 0,
    match: Union[PatternT, None] = None,
    count: Union[int, None] = None,
) -> ResponseT:

count不准确,有点上下浮动。

res = conn.hscan('test', cursor=0, count=7)
print(res)
print(len(res[1]))
print(res[0])
res = conn.hscan('test', cursor=res[0], count=7)
print(res)
print(len(res[1]))
print(res[0])

hscan_iter()

使用HSCAN命令创建一个迭代器,这样客户端就不需要迭代,需要记住光标的位置。
match允许按模式过滤键
count允许提示最小返回次数

def hscan_iter(
     self,
     name: str,
     match: Union[PatternT, None] = None,
     count: Union[int, None] = None,
 ) -> Iterator:
    cursor = "0"
    while cursor != 0:
        cursor, data = self.hscan(name, cursor=cursor, match=match, count=count)
        yield from data.items()

res = conn.hscan_iter('test')
print(res)  # 生成器 <generator object ScanCommands.hscan_iter at 0x000001ADF783B9E0>


for i in res:
    print(i)
conn.close()


列表操作

1 lpush(name,values)
2 lpushx(name,value)
3 rpushx(name, value) 表示从右向左操作
4 llen(name)
5 linsert(name, where, refvalue, value))
6 lset(name, index, value)
7 lrem(name, value, num)
8 lpop(name)
9 lindex(name, index)
10 lrange(name, start, end)
11 ltrim(name, start, end)
12 rpoplpush(src, dst)
13 blpop(keys, timeout)
14 brpoplpush(src, dst, timeout=0)
15 自定义增量迭代


lpush()

将values推到列表的头部name

def lpush(self, name: str, *values: FieldT) -> Union[Awaitable[int], int]:

res = conn.lpush('redis_list', 1, 2, 3, 4, 5)
print(res)  # 5

lpushx()

如果name存在,将value推到name的头部

def lpushx(self, name: str, *values: FieldT) -> Union[Awaitable[int], int]:

res = conn.lpushx('redis_list', 6, 7, 8)
print(res)  # 8

rpush()和rpushx()

与上面两个相反,推到列表的尾部。

llen()

返回列表的长度name

def llen(self, name: str) -> Union[Awaitable[int], int]:

res = conn.llen('redis_list')
print(res)  # 8

linsert()

在列表中插入元素,该元素存储在基准值基准值之前或之后。
如果key不存在,则认为它是一个空列表,不会执行任何操作。
如果key存在但没有保存列表值,则返回错误。

def linsert(
     self, name: str, where: str, refvalue: str, value: str
 ) -> Union[Awaitable[int], int]:

res = conn.linsert('redis_list', 'before', '3', 'new')
print(res)  # 9

lset()

将list name的index元素设置为value

def lset(self, name: str, index: int, value: str) -> Union[Awaitable[str], str]:
res = conn.lset('redis_list', 0, 'lset')
print(res)  # True

lrem()

删除第一次count等于value的元素从存储在name中的列表中。

def lrem(self, name: str, count: int, value: str) -> Union[Awaitable[int], int]:
res = conn.lrem('redis_list', 1, '5')
print(res)  # 1

lpop()

删除并返回列表name的第一个元素。

默认情况下,该命令从开头弹出一个元素从列表中。当提供可选的count参数时,响应将由多数量的元素组成,这取决于列表的长度。

从 Redis 版本 6.2.0 开始:添加了参数count。

def lpop(self, name: str, count: Optional[int] = None) -> Union[str, List, None]:
res = conn.lpop('redis_list')
print(res)  # b'lset'

lindex()

从列表name中返回位置index
支持负索引,从列表末尾开始

def lindex(
     self, name: str, index: int
 ) -> Union[Awaitable[Optional[str]], Optional[str]]:

res = conn.lindex('redis_list', 0)
res1 = conn.lindex('redis_list', -1)

lrange()

返回列表name之间的一个切片
定位start和end
start和end也可以是负数
Python切片表示法

def lrange(self, name: str, start: int, end: int) -> Union[Awaitable[list], list]:
res = conn.lrange('redis_list',0,-1)
print(res)

ltrim()

修剪列表name,删除所有不在切片内的
在start和end之间

start和end也可以是负数

Python切片表示法

def ltrim(self, name: str, start: int, end: int) -> Union[Awaitable[str], str]:
res = conn.ltrim('redis_list',1,-2)

rpoplpush()

从src列表中取出一个值RPOP,然后在dst列表上LPUSH。并返回rpop的值。

def rpoplpush(self, src: str, dst: str) -> Union[Awaitable[str], str]:
conn.lpush('new_list', '1')
res = conn.rpoplpush('redis_list', 'new_list')
print(res)  # b'new'

blpop()

从第一个非空列表中取出一个值

在 keys 列表中命名。

如果keys中的列表都没有值可以LPOP,则阻塞timeout秒,或者直到一个值被推送给一个值名单的。

如果timeout为0,则无限期阻塞。

def blpop(
     self, keys: List, timeout: Optional[int] = 0
 ) -> Union[Awaitable[list], list]:

res = conn.blpop('redis_list')
print(res)

brpoplpush()

BRPOPLPUSH是RPOPLPUSH 的阻塞变体。 当包含元素时,此命令的行为与RPOPLPUSH 完全相同。 当在MULTI/EXEC块中使用时,此命令的行为与RPOPLPUSH 完全相同。 当为空时,Redis 将阻止连接,直到另一个客户端 推到它或直到到达。 零点可用于无限期阻止。

def brpoplpush(
     self, src: str, dst: str, timeout: Optional[int] = 0
 ) -> Union[Awaitable[Optional[str]], Optional[str]]:
conn.lpush('redis_list', 1, 2, 3, 4)
res = conn.brpoplpush('redis_list', 'new_list')
print(res)

redis管道

MySQL事务的四大特性为ACID:隔离性,一致性,原子性,永久性。 

redis数据库是否支持事务呢?

redis事务机制留一保证一致性和隔离性, 无法保证持久性,打死你hi对于redis而言,本身他是应该内存数据库,所以持久化不是必须属性, 原子性需要自己进行检测,尽可能保证。 

redis不像mysql一样支持强事务, 事务的四大特性只能满足其中一部分, 但是通过redis的管道可以实现部分事务。

redis通过管道,来保证命令要么都成功,要么都失败, 完成十五的一致性,但是管道只能哟弄个在单实例,集群的环境中,不支持pipline


import redis

conn = redis.Redis()  # 实例化
pipline = conn.pipeline(transaction=True)
pipline.decr('a', 2)  # a减2
raise Exception('我崩了')
pipline.incr('b', 2)  # b加2
pipline.execute()
conn.close()

redis其他操作

集合,有序集合, redis模块提供的方法API

通用操作: 五大类行都支持

import redis

conn = redis.Redis()
# 1 delete(*names)
conn.delete('age', 'name')

# 2 exists(name)
res=conn.exists('xx')
print(res)  # 0


# 3 keys(pattern='*')
res=conn.keys('*o*')
# res=conn.keys('?o*')
print(res)

# 4 expire(name ,time)
conn.expire('test_hash',3)


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


# 6 move(name, db) # 将redis的某个值移动到指定的db下
# 默认操作都是0 库,总共默认有16个库
conn.move('xxx',2)


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

# 8 type(name)  查看类型
res = conn.type('aa')  # list  hash set
print(res)

conn.close()

django中集成redis

方式一: 直接使用

from user.POOL import pool
import redis
def index(request):
    conn = redis.Redis(connection_pool=pool)
    conn.incr('page_view')
    res = conn.get('page_view')
    return HttpResponse('被你看了%s次' % res)

方式二: 使用第三方模块django-redis

下载模块:

 pip3 install django=redis

配置文件配置

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

使用

 from django_redis import get_redis_connection
 def index(request):
        conn = get_redis_connection(alias="default") # 每次从池中取一个链接
        conn.incr('page_view')
        res = conn.get('page_view')
        return HttpResponse('被你看了%s次' % res)

方式三: 借助于django的缓存使用redis

如果配置文件配置了CACHES,以后django的缓存,数据直接放在redis中

直接使用cache.set设置值,【可以上传过期时间】

使用cache.get来获取值。 其强大之处在于: 可以直接缓存任意的python对象,因为其底层使用的pickle实现的。pickle可以序列化python的任意数据类型

访问test 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值