初识Redis

2023-05-16

什么是Redis

Remote Dictionary Server,即远程字典服务,是一款开源的、基于内存也支持持久化的key-value数据库,提供多种语言API。通常应用于需要处理大规模数据读写的场景中。

和其它关系型数据相比,其有以下优势:

  • 基于内存,读写操作性能优越,可以支持每秒十几万次的读写操作;

  • 支持集群、分布式、主动同步等配置;

  • 具备事务能力,保证了高并发场景下数据的安全和一致性。

数据结构

Redis支持五种数据结构:

  • 字符串(string):value中存储的是一个字符串,编码格式是raw或int

  • 哈希(hash):value中存储的是一个哈希映射表(hashmap),redis提供了存取该哈希表内容的接口;

  • 列表(list):value是通过一个双向链表存储;

  • 集合(set):即hashset,可以将重复的元素放入而set会自动去重,底层实现是哈希映射表(hashmap),一个value永远是null的hashmap。

  • 有序集合(zset):内部使用hashmap和跳跃表skiplist来保证数据的存储和有序。Sorted Set的实现是HashMap(element->score, 用于实现ZScore及判断element是否在集合内),和SkipList(score->element,按score排序)的混合体。SkipList有点像平衡二叉树那样,不同范围的score被分成一层一层,每层是一个按score排序的链表。

python API

1. 数据库连接

  • 直接连接

import redis
# 直接连接
red = redis.Redis(host='localhost', port=6379, db=1)
  • 连接池连接

import redis
pool = redis.ConnectionPool(host='localhost', port=6379, db=1)
red = redis.Redis(connection_pool=pool)

连接池连接原理是,通过预先创建多个连接,当进行redis操作时可以直接获取已经创建的连接进行操作,而且操作完成后不会释放,用于后续的其它redis操作;这样可以避免频繁地进行redis创建和释放,从而提高性能。

2. 数据存取

# String类型存取
red.set('key', 'value') # 默认不存在则创建,存在则修改
red.setex('key', 'value', time) # 设置过期时间,秒,px为毫秒
red.mset({'key1':'value1', 'key2':'value2'}) # 批量设置值
red.mget({'key1':'value1', 'key2':'value2'}) # 批量获取值
red.get('key') # 获取'key'对应的值
red.strlen('key') # 返回'key'对应值的长度
red.append('key', 'hello') # 在‘key’对应的值后面追加内容
# Hash类型存取,hash即一个name对应一个dic字典
red.hset('name', 'key', 'value') # 设置一对key-value,不存在则创建,存在则修改
red.hget('name', 'key')
red.hmset('name', dic)
red.hgetall('name')
red.hmget('name', 'key1', 'key2') # 批量输出键对应的值
red.hlen('name') # 获取hash键值对个数
red.hkeys('name') # 获取hash中的所有key
red.hvals('name') #获取hash中所有value
red.hexists('name', 'key') 
red.hdel('name', 'key') # 删除key对应的键值对
red.incrby('name', 'key', amount=10) # 将amount的值与hash中key对应的值相加,key不存在则创建key=amount(amount为整数)
# list类型存取,list即一个name对应一个列表
red.lpush('name', 'list_item1', 'list_item2') # 元素从list左边添加
red.rpush('name', 'list_item1', 'list_item2') # 元素从list右边添加
red.lpushx('name', 'list_item1', 'list_item2') # 当name存在时,元素从list左边添加
red.rpushx('name', 'list_item1', 'list_item2') # 当name存在时,元素从list右边添加
red.llen('name')
red.linsert('name', BEFORE/AFTER, 'item1', 'item2') # 在列表中找到第一个元素’item1‘,在他的前面插入'item2'
red.lset('name', index, value) 
red.lrem('name', value, num=0) # 删除list中的value值,num=0删除列表中所有的value值,num=2从前往后删除两个,num=-2从后向前删除两个
red.lpop('name') # 删除list左侧第一个元素,并返回
red.lindex('name', index)
red.lrange('name', start_index, end) # 分片获取list元素
red.ltrim('name', 0, 2) # 移除list中没有在该索引(0-2)之内的值
# set类型存取,set即不允许重复的列表
red.sadd('name', 'item1')
red.sadd('name', 'item1', 'item2')
red.scard('name') # 获取集合中的元素个数
red.smembers('name')
red.sdiff('name', 'name1', 'name2') # 在'name'中,且不在'name1'和'name2'的元素
red.sismember('name', 'item') # 检测’item‘是否是’name‘集合中的元素
red.smove('name1', 'name2', 'item') # 将’item‘从’name1‘中移到’name2‘中
red.spop('name') # 从集合的右侧移除一个元素其它常用操作

3. 其它常用操作

red.flushdb(asynchronous=False) # 清空当前db中的数据,默认同步
red.flushall(asynchronous=False) 

4.管道

redis默认在执行每次操作请求时都会创建和断开连接,或者去连接池申请连接和释放连接,这就需要在服务器和客户端之前反复进行TCP数据包的传送。而管道(pipeline)可以实现一次请求指定多个命令,并且默认一次pipeline是原子性操作。

import redis
​
pool = redis.ConnectionPool(host='localhost', prot=6379, decode_response=True) # decode_response=True,默认取出结果是字节,true返回字符串
red = redis.Redis(connection_pool=pool)
# 创建管道
pipe = red.pipeline()
# 向管道里注入命令
pipe.set('name', 'jane')
pipe.sadd('gender', 'male')
# 执行管道命令
pipe.execute()
​
# 命令和执行可以连起来

Redis事务

Redis事务本质上是一组命令的集合。

Redis事务不保证原子性,且没有回滚。事务中的单条命令是原子性执行的,事务中任意命令执行失败,其余命令会继续被执行。

Redis事务的三个阶段:

  1. 开始事务(MULTI)

  2. 命令入队

  3. 执行事务(EXEC)

相关指令

MULTI:标记一个事务的开始

EXEC: 执行事务中的所有命令

DISCARD: 取消事务,放弃事务中的所有命令

WATCH keyname:监视一个或多个key,如果事务执行之前被监视的key被改动,则事务将被打断(类似乐观锁)

UNWATCH: 取消watch对所有key的监控

分布式锁

分布式锁是用来解决实际应用中并发冲突的一种手段。

# 分布式锁实现
class RedisLock(object):
    def __init__(self, lock_name, identifier, expire=10):
        pool = redis.ConnectionPool(host='10.68.4.*', port='6479', password='root', db=3)
        self.conn = redis.Redis(connection_pool=pool)
        self.lock_name = lock_name
        self.identifier = identifier
        self.expire = expire
​
    # 获取锁
    def acquire_lock(self):
        if self.conn.setnx(self.lock_name, self.identifier):
            self.conn.expire(self.lock_name, self.expire)
            return self.identifier
        elif not self.conn.ttl(self.lock_name):
            self.conn.expire(self.lock_name, self.expire)
        return False
​
    # 释放锁
    def release_lock(self):
        pipe = self.conn.pipeline()
        while True:
            try:
                pipe.watch(self.lock_name)
                if pipe.get(self.lock_name) == self.identifier:
                    pipe.delete(self.self.lock_name)
                    pipe.execute()
                    return True
                pipe.unwatch()
                break
            except redis.exceptions.WatchError:
                pass
        return False
​
count = 10
def func(thread_index):
    my_lock = RedisLock('locker_name', 'ticket')
    my_lock.acquire_lock()
    print("线程:{}--得到了锁".format(thread_index))
    global count
    if count < 1:
        print("线程:{}--没抢到票,票被抢完了".format(thread_index))
    count -= 1
    my_lock.release_lock()
​
if __name__ == '__main__':
    for i in range(50):
        t = threading.Thread(target=func, args=(i,))
        t.start()

这里没有加获取锁的超时时间。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

初识Redis 的相关文章

  • Redis hash写入速度非常慢

    我面临一个非常奇怪的问题 使用 Redis 时 我的写入速度非常糟糕 在理想的情况下 写入速度应该接近 RAM 上的写入速度 这是我的基准 package redisbenchmark import redis clients jedis
  • redis-cli 重定向到 127.0.0.1

    我在PC1上启动Redis集群 然后在PC2上连接它 当需要重定向到另一个集群节点时 它会显示Redirected to slot 7785 located at 127 0 0 1 但应该显示Redirected to slot 7785
  • Redis 排序集和解决关系

    我正在使用 Redis 排序集来存储我正在处理的项目的排名 我们没有预料到 我们想要如何处理关系 Redis 按字典顺序对具有相同分数的条目进行排序 但我们想要做的是对具有相同分数的所有条目给予相同的排名 例如在以下情况 redis 127
  • Redis INCRBY 有限制

    我想知道是否有一种方法可以通过我的应用程序的单次往返在 Redis 中执行此操作 对于给定的键K 其可能值V是范围内的任意整数 A B 基本上 它有上限和下限 When an INCRBY or DECRBY发出命令 例如INCRBY ke
  • 如何测试我的 Redis 缓存是否正常工作?

    我已经安装了 django redis cache 和 redis py 我遵循了 Django 的缓存文档 据我所知 以下设置就是我所需要的 但我如何判断它是否正常工作 设置 py CACHES default BACKEND redis
  • 使用Redis从有限范围内生成唯一ID

    我有一些数据库项目 除了主键之外 还需要项目所属组的唯一索引 我们来调用属性nbr 以及将项目分组在一起并定义唯一范围的属性nbr 我们会打电话group This nbr必须在 1 N 范围内 并且may从外部源导入项目时进行设置 由于所
  • 如何在Redis中进行持久化存储?

    关闭redis服务器后 使用set存储的值被破坏 在这里我找到了使用持久性存储的方法 有人帮助我 如何使用javascript实现这一点 我想将客户端的一些值存储在 redis 数据库中 并且必须在其他客户端中使用该值 您需要配置 Redi
  • Lua中按字符分割字符串

    我有像这样的字符串 ABC DEF 我需要将它们分开 字符并将两个部分分别分配给一个变量 在 Ruby 中 我会这样做 a b ABC DEF split 显然Lua没有这么简单的方法 经过一番挖掘后 我找不到一种简短的方法来实现我所追求的
  • 使用 Sentinels 升级 Redis 的最佳实践?

    我有 3 个 Redis 节点 由 3 个哨兵监视 我进行了搜索 文档似乎不清楚如何最好地升级此类配置 我目前使用的是 3 0 6 版本 我想升级到最新的 5 0 5 我对这方面的程序有几个疑问 升级两个大版本可以吗 我在我们的暂存环境中执
  • Redis、会话过期和反向查找

    我目前正在构建一个网络应用程序 并想使用 Redis 来存储会话 登录时 会话会使用相应的用户 ID 插入到 Redis 中 并且过期时间设置为 15 分钟 我现在想实现会话的反向查找 获取具有特定用户 ID 的会话 这里的问题是 由于我无
  • Spring Data JPA Redis:无法编写基于自定义方法的查询

    我已经使用 Redis 配置了 Spring Data JPA 并使用RedisRepositorieswith 提供了类似的方法find findAll 所有这些方法似乎都工作得很好 但我无法编写我的自定义方法 RedisEntity f
  • 有没有办法让特定的key在集群模式下定位到特定的redis实例上?

    我想让我的多锁位于不同的redis实例上 我发现redission可以指定一个实例来执行命令 但是如果该命令与key相关 则指定的实例会将命令传输到另一个实例 你能给我一些建议吗 你可以 但这并不是微不足道的 首先 Redis 在键中使用大
  • StackExchange.Redis的正确使用方法

    这个想法是使用更少的连接和更好的性能 连接会随时过期吗 对于另一个问题 redis GetDatabase 打开新连接 private static ConnectionMultiplexer redis private static ID
  • Scala 使用的 Redis 客户端库建议

    我正在计划使用 Scala 中的 Redis 实例进行一些工作 并正在寻找有关使用哪些客户端库的建议 理想情况下 如果存在一个好的库 我希望有一个为 Scala 而不是 Java 设计的库 但如果现在这是更好的方法 那么仅使用 Java 客
  • 如何在Redis中只保存一个数据库?

    我是 Redis 新手 有一个与备份相关的问题 目前 我有一个实例在 Windows 服务器上运行 在这个实例中 我当前有一项 工作 将数据存储在一个数据库中 我不想备份这些数据 我必须创造一份新工作 我的第一个想法是将数据存储在另一个数据
  • Laravel 异常队列最大尝试次数超出

    我创建了一个应用程序来向多个用户发送电子邮件 但在处理大量收件人时遇到问题 该错误出现在failed jobs table Illuminate Queue MaxAttemptsExceededException App Jobs ESe
  • Redis 中存储整数和字符串的区别

    这两个命令有什么区别吗 LPUSH myset 123 LPUSH myset 123 我想存储大约 500 万个整数 并且我想以最有效的方式做到这一点 不 没有什么区别 两者都存储为字符串 从redis io http redis io
  • 为什么我们需要 Redis 来运行 CKAN?

    我想知道为什么我们需要 Redis 服务器来运行 CKAN 如果需要 为什么 我如何使用 CKAN 配置它 附注 我正在 RHEL7 中运行我的 ckan 实例 Update Redis 已成为一项要求从CKAN 2 7开始 https d
  • 检查 Redis 列表中是否已存在某个值

    我想知道是否有办法检查 redis 列表中是否已存在某个键 我无法使用集合 因为我不想强制唯一性 但我确实希望能够检查字符串是否确实存在 Thanks 您的选择如下 Using LREM如果发现则更换它 维护一个单独的SET与您的LIST
  • 无法使用 ASP.NET 会话状态提供程序连接到 Redis 服务器

    一段时间以来 我一直在尝试用 Redis 替换 ASP NET Session 多个小时与适用于 Redis 的 Microsoft ASP NET 会话状态提供程序 http blogs msdn com b webdev archive

随机推荐

  • ARDUINO LCD显示简单的汉字、符号(二 已写成的字模和基于Python的检索系统)

    北 61 0x0A 0x0A 0x0A 0x1B 0x0A 0x0A 0x0A 0x1B 京 61 0x04 0x1F 0x0E 0x0A 0x0E 0x15 0x15 0x0C 市 61 0x04 0x1F 0x04 0x1F 0x15
  • MindSpore图像分类训练resnet50实现

    目录 一 mindspore简介 二 训练环境 三 数据集与数据加载 四 模型训练和验证 五 迁移学习 六 模型测试和导出 一 mindspore简介 MindSpore 是华为开源的全场景深度学习框架 xff0c 旨在实现易开发 高效执行
  • 最快的远程控制软件radmin的配置和使用

    Remote Administrator Radmin 是最快的远程控制软件 又因为它不被杀毒软件查杀 从而成为远程控制的首选 nbsp 一 radmin的配置 首先下载并解压Radmin2 1 解压后有七个文件 打开 配置r server
  • 介绍一个成功的 Git 分支模型

    英文原文 xff0c A successful Git branching model xff0c 翻译 xff1a 开源中国 在这篇文章中 xff0c 我提出一个开发模型 我已经将这个开发模型引入到我所有的项目里 xff08 无论在工作还
  • 浪潮服务器通过BMC远程安装系统

    浪潮服务器的BMC xff0c 类似于IBM服务器的IPMI xff0c 可以远程安装系统或者其他操作 前提 xff1a 1 带外ip xff1a 192 168 1 100 在bios的 lan channel 1 里面配置带外ip xf
  • Linux|错误集锦|prometheus Error on ingesting samples that are too old or are too far into the future的解决

    前情回顾 xff1a 二进制prometheus部署完成后 xff0c 在prometheus的web界面进行一些数据验证工作 下面这个是我已经恢复正常的 xff0c 其实是查询不到数据的 grafana也接收不到任何数据 问题排查 xff
  • 《软件工程导论》/ 第一章 软件工程学概述 / 1.3 软件生命周期

    概括地说 xff0c 软件生命周期由3个时期组成 xff0c 每个时期又进一步划分成若干个阶段 xff1a 软件定义 xff08 问题定义 可行性研究 需求分析 xff09 软件开发 xff08 总体设计 详细设计 编码和单元测试 综合测试
  • python开发PC端桌面应用

    项目场景 xff1a 很多情况下需要用很短的时间开发一款在windows上离线运行的小工具 xff0c 以便解决一些现实问题 比如公司近期有个紧急项目 xff0c 需要根据算法需求人工标注海量的地址信息 xff0c 开发周期和工具易用性上都
  • Vue和Flask实现前后端分离

    引言 近期了解了下目前比较热门的前端框架Vue js xff0c 新技能嘛 xff0c 只有实践了用起来了 xff0c 才能有比较直观的体验 因此考虑写个小demo练练手 xff0c 后端采用Flask提供几个Restfull风格的API
  • C/S架构的应用程序开发实战(一)

    项目背景 近期需要开发一个对巨量的图片数据进行车辆品牌信息标注的工具 xff0c 为了提高标注效率 xff0c 准备先通过现有车辆品牌识别的算法模型进行下预标注 xff0c 标注人员在此基础上进行审核和修改即可 另外 xff0c 需要统计出
  • Nginx服务安全漏洞修复

    1 安全漏洞说明 使用Nginx提供服务的产品 xff0c 经过安全扫描工具扫描后报出三个高风险 三个中风险安全漏洞 2 nginx版本过低自带安全漏洞 升级nginx版本到1 21 1后 xff0c 三个高风险漏洞消失 3 HTTP 信息
  • C/S架构的应用程序开发实战(二)

    后端服务 后端用python实现 xff0c 采用flask web框架 可从github上获取flasky源码 xff0c 在此基础上进行业务逻辑的实现 程序结构如下 xff1a app 业务逻辑实现代码 common 公共函数实现 这里
  • MySql安装相关

    windows安装mysql xff1a 1 获取并解压安装包 xff1a mysql 8 0 20 winx64 zip 2 配置环境变量 xff1a 3 管理员权限打开cmd xff0c 进入安装目录 xff1a H gt cd H t
  • MySql之索引

    通常小型项目涉及数据量比较小 xff0c 数据查询频率不高 xff0c 索引通常会被忽略 但当数据量较大 xff0c 涉及多个表 xff0c 查询较为频繁时 xff0c 我们需要对查询性能进行优化 xff0c 此时 xff0c 建立合适的索
  • jupyter-notebook二次开发

    背景 公司内部提供给算法人员用于模型训练的平台开发需求中提出了嵌入Jupyter Notebook模块 xff0c 而Jupyter Notebook是开源的 xff0c 方便后续对部分细节进行功能定制和优化 xff0c 需要对其进行调研
  • python中大数据文件读取

    python中大数据文件读取 python中经常会遇到读取大文件的场景 文件较小时 xff0c 我通常采用下面方法 xff0c readlines xff08 xff09 xff0c 该方法会一次性读取文件的所有行 xff0c 并将其放入l
  • Linux|奇怪的知识|locate命令---文件管理小工具

    前言 Linux的命令是非常多的 xff0c 有一些冷门的命令 xff0c 虽然很少用 xff0c 但可能会有意想不到的功能 xff0c 例如 xff0c 本文将要介绍的locate命令 xff08 平常很少会想到使用此命令 xff0c f
  • python之装饰器

    引言 软件开发中 xff0c 当需要创建高度重复的代码时 xff0c 需要寻求一种优雅的解决方案 python中的元编程即解决这类问题 xff0c 通过创建函数和类来修改 生成或包装已有的代码 装饰器就是python中用来包装函数的一种机制
  • docker容器中程序退出异常,GPU未释放

    1 问题描述 近期在docker容器中对一批数据通过算法进行清洗时 xff0c 当数据处理完成后发现进程未正常退出 xff0c GPU内存未正常释放 span class token punctuation span root 64 ai6
  • 初识Redis

    什么是Redis Remote Dictionary Server xff0c 即远程字典服务 xff0c 是一款开源的 基于内存也支持持久化的key value数据库 xff0c 提供多种语言API 通常应用于需要处理大规模数据读写的场景