Redis数据存储和读写
今天工作群里,有小伙伴问了一个问题,从Redis获取的数据,一会是0,一会是OK。
这引起了我们对Redis数据存储和读写的疑问。
以下是整理的一些技术研究内容。
在 Redis 中,所有的数据存储都是基于字符串的。无论你插入的是 String、int 还是 DateTime 类型的数据,最终都会以字符串的形式存储在 Redis 中。具体来说:
String 类型数据:
- 存储:直接以字符串形式存储,无需额外处理。
- 取出:直接取出字符串即可。
int 类型数据:
- 存储:将 int 类型转换为字符串,然后存储。
- 取出:从 Redis 中取出字符串后,再转换为 int 类型。
DateTime 类型数据:
- 存储:通常将 DateTime 类型转换为某种标准格式的字符串(如 ISO 8601 格式),然后存储。
- 取出:从 Redis 中取出字符串后,再解析为 DateTime 类型。
具体的操作示例如下:
插入数据
import redis
from datetime import datetime # 连接到 Redis
r = redis.StrictRedis(host='localhost', port=6379, db=0) # 存储 String 数据
r.set('my_string', 'Hello, Redis!') # 存储 int 数据
r.set('my_int', str(12345)) # 存储 DateTime 数据
now = datetime.now().isoformat()
r.set('my_datetime', now)
取出数据
# 取出 String 数据
my_string = r.get('my_string').decode('utf-8') # 取出 int 数据
my_int = int(r.get('my_int')) # 取出 DateTime 数据
my_datetime = datetime.fromisoformat(r.get('my_datetime').decode('utf-8'))
数据类型转换:当你从 Redis 取出数据时,Redis 返回的是字节字符串,你需要根据存储的数据类型进行相应的转换:
- **String 数据:**直接解码为字符串。
- **int 数据:**先解码为字符串,然后转换为整数。
- **DateTime 数据:**先解码为字符串,然后解析为 DateTime 对象。
这种方式虽然简单直接,但需要在应用层处理数据的序列化和反序列化。
我们可以根据需要选择不同的序列化格式(如 JSON、Protobuf 等)来存储更复杂的数据结构。
数据的序列化和反序列化确实会引入一些性能开销,但在大多数情况下,这些开销是可以接受的。具体的性能影响取决于以下几个因素:
数据量大小: 如果数据量较小,序列化和反序列化的开销通常是微不足道的。但是对于大数据量,这些操作的成本会显著增加。
序列化方式: 不同的序列化方式有不同的性能特征。例如,简单的字符串序列化通常比复杂的格式(如 JSON、XML 或 Protobuf)要快。
数据类型和复杂度: 简单的数据类型(如整数和字符串)比复杂的数据类型(如对象或嵌套结构)更容易序列化和反序列化。
为了减少序列化和反序列化的性能问题,可以考虑以下几种优化方法:
选择高效的序列化格式: 对于简单的数据类型,直接使用字符串或二进制格式可以减少开销。对于复杂数据类型,可以选择性能更好的序列化格式,如 MessagePack 或 Protobuf。
减少数据量: 仅存储和传输必要的数据,尽量减少每次操作的数据量。
批量操作: 批量操作可以减少网络开销。例如,使用 Redis 的批量命令(如 MSET 和 MGET)一次性操作多个键值对。
缓存计算结果: 对于需要频繁计算的数据,可以将计算结果缓存到 Redis 中,避免每次都进行序列化和反序列化操作。
Redis 是一个基于内存的高性能键值存储系统,采用了多种数据结构来优化数据存储和访问效率。下面是 Redis 内部数据存储的一些关键原理和机制:
数据结构
Redis 支持多种数据结构,每种数据结构有其特定的存储方式:
字符串(String)
- 存储:Redis 的字符串是二进制安全的,最长可以存储 512 MB 的数据。字符串数据结构采用简单动态字符串(SDS)来实现,这种结构允许高效的字符串操作和内存管理。
- 数据结构:SDS 是一种带有元数据(如长度和空余空间)的动态数组。
哈希(Hash)
- 存储:哈希表用于存储键值对集合,适合存储对象的属性数据。
- 数据结构:采用哈希表(dict)实现。小哈希表(元素少于一定数量时)采用 ziplist(压缩列表)优化存储,大哈希表则使用标准的哈希表实现。
列表(List)
- 存储:列表用于存储有序的字符串集合,支持快速的头尾插入和删除操作。
- 数据结构:列表小于一定大小时使用 ziplist 实现,较大时使用双向链表(quicklist)实现。
集合(Set)
- 存储:集合用于存储无序的字符串集合,支持快速的添加、删除和成员检查操作。
- 数据结构:小集合使用整数数组(intset)实现,大集合使用哈希表实现。
有序集合(Sorted Set)
- 存储:有序集合在集合的基础上为每个成员关联一个分数,成员按分数排序。
- 数据结构:采用跳表(skiplist)和哈希表联合实现,跳表用于排序,哈希表用于快速查找。
位图(Bitmap)
- 存储:位图用于高效地存储和操作大量的二进制数据。
- 数据结构:底层实现为字符串,按位操作。
HyperLogLog
- 存储:用于基数估计算法,估算集合中不重复元素的数量。
- 数据结构:底层使用稀疏和稠密两种表示法来优化空间使用。
地理空间(Geo)
- 存储:用于存储地理位置信息。
- 数据结构:基于有序集合实现,通过 GEOADD、GEORADIUS 等命令操作。
内存管理
Redis 采用多种内存管理技术来优化性能和内存使用:
- 内存分配:Redis 使用 jemalloc 作为默认的内存分配器,可以高效地管理内存碎片和分配。
- 对象共享:对于常用的小对象(如小整数),Redis 会在内部共享这些对象,减少内存开销。
- 内存压缩:对于字符串等数据,Redis 可以使用压缩技术来减少内存使用。
- LRU/LFU 淘汰:当内存达到设定的上限时,Redis 可以根据设定的策略(如 LRU 或 LFU)淘汰不常用的数据。
持久化
为了防止数据丢失,Redis 提供了多种持久化机制:
- RDB 快照:定期将内存中的数据快照保存到磁盘。优点是数据恢复速度快,但可能丢失最近的数据。
- AOF 日志:记录每个写操作,定期将日志刷新到磁盘。优点是数据持久化更可靠,但恢复速度较慢。
- 混合模式:结合 RDB 和 AOF 的优点,先加载 RDB 快照,然后应用 AOF 日志。
哨兵和集群
为了实现高可用性和扩展性,Redis 提供了哨兵模式和集群模式:
- 哨兵模式:通过哨兵进程监控 Redis 主从节点的状态,自动进行故障转移。
- 集群模式:将数据分片存储到多个节点上,通过哈希槽(hash slot)实现数据分布和访问。
Redis 内部通过这些机制和原理,提供了高效、可靠的键值存储和访问服务。
Redis数据存储和读写的更多相关文章
- redis数据存储的细节
redis是一个K-V NoSql非关系型数据库,redis有物种数据类型,分别是String,Hash,list,set,zset:这五种类型都是针对K-V中的V设计的. 1.总体介绍:关于redi ...
- Redis数据存储解决方案
http://www.tuicool.com/articles/77nUZn 1.背景 1.1 Redis简介 官方网站: http://redis.io/ ,Redis是REmote DIction ...
- Redis数据存储优化机制(转)
原文:Redis学习笔记4--Redis数据存储优化机制 1.zipmap优化hash: 前面谈到将一个对象存储在hash类型中会占用更少的内存,并且可以更方便的存取整个对象.省内存的原因是新建一个h ...
- 直接在安装了redis的Linux机器上操作redis数据存储类型--String类型
一.概述: 字符串类型是Redis中最为基础的数据存储类型,它在Redis中是二进制安全的,这便意味着该类型可以接受任何格式的数据,如JPEG图像数据或Json对象描述信息等.在Redis中字符串类型 ...
- Redis数据存储结构之String
前言: 在Redis使用中,我们最常使用的操作是set key value,或 get key value .这里面包含了redis最基本的数据类型:String,字符串类型是redis中最基本的类型 ...
- 第十三节:web爬虫之Redis数据存储
下面仅仅展示Redis的set()集合存储,并不完整,后期会对Redis进行全面的介绍.... 此时数据已经存储到Redis当中
- 直接在安装了redis的Linux机器上操作redis数据存储类型--对key的操作
一.概述: 前几篇博客中,主要讲述的是与Redis数据类型相关的命令,如String.List.Set.Hashes和Sorted-Set.这些命令都具有一个共同点,即所有的操作都是针对与Key关 ...
- 直接在安装了redis的Linux机器上操作redis数据存储类型--set类型
一.概述: 在Redis中,我们可以将Set类型看作为没有排序的字符集合,和List类型一样,我们也可以在该类型的数据值上执行添加.删除或判断某一元素是否存在等操作.需要说明的是,这些操作的时间复 ...
- 直接在安装了redis的Linux机器上操作redis数据存储类型--hash类型
一.概述: 我们可以将Redis中的Hashes类型看成具有String Key和String Value的map容器.所以该类型非常适合于存储值对象的信息.如Username.Password和 ...
- 直接在安装了redis的Linux机器上操作redis数据存储类型--List类型
一.概述: 在Redis中,List类型是按照插入顺序排序的字符串链表.和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素.在插入时,如果该键并不存在,Redis ...
随机推荐
- OAM 深入解读:OAM 为云原生应用带来哪些价值?
导读:OAM 是阿里巴巴联合微软在社区推出的一款用于构建和交付云原生应用的标准规范,旨在通过全新的应用定义.运维.分发与交付模型,推动应用管理技术向"轻运维"的方向迈进,全力开启下 ...
- 从托管到原生,MPP架构数据仓库的云原生实践
简介:本文介绍了云原生数据仓库产品AnalyticDB PostgreSQL从Cloud-Hosted到Cloud-Native的演进探索,探讨为了实现真正的资源池化和灵活售卖的底层设计和思考,涵盖 ...
- 参与 Apache 顶级开源项目的 N 种方式,Apache Dubbo Samples SIG 成立!
简介: 一说到参与开源项目贡献,一般大家的反应都是代码级别的贡献,总觉得我的代码被社区合并了,我才算一个贡献者,这是一个常见的错误认知.其实,在一个开源社区中有非常多的角色是 non-code con ...
- 当设计模式遇上 Hooks
简介: 数据结构与设计模式能够指导我们在开发复杂系统中寻得一条清晰的道路,既然都说 Hooks 难以维护,那就尝试让「神」来拯救这混乱的局面.对于「设计模式是否有助于我们写出更优雅的 Hooks 」 ...
- [php-src] Php内核的有趣高频宏
内容均以php-5.6.14为例. 1. EXPECTED 和 UNEXPECTED 宏,用在判断条件的时候. ./Zend/zend.h:390 #if (defined (__GNUC__) &a ...
- WPF 制作一个占用文件的测试工具
我在开发软件进行测试时,需要测试拖入的文件被占用时软件的行为,于是就做了一个文件占用工具,此工具可以将某个文件进行占用,以及获取某个文件被哪个进程占用 先给大家看一下效果: 以上是拖入文件到灰色部分, ...
- dotnet 修复在 Linux 上使用 SkiaSharp 提示找不到 libSkiaSharp 库
本文告诉大家如何简单修复在 Linux 上使用 SkiaSharp 提示找不到 libSkiaSharp 库 我的应用在 Windows 上跑的好好的,放在 Linux 上一运行就炸掉了,异常内容如下 ...
- ESP32 分区表
当你编译程序,发现 app partition is too small for binary 错误的时候,就涉及到 ESP32 分区表的内容了. 一.基本概念 在了解分区之前,先了解一下以下概率,便 ...
- RT-Thead移植时缺少SystemCoreClockUpdate函数
一.问题 在移植 RT-Thead 时,需要获取mcu当前的 HCLK 时钟频率来设置滴答时钟,而我使用的库函数中刚好缺少SystemCoreClockUpdate函数. 我之前在RT-Thread移 ...
- 【2023微博评论爬虫】用python爬上千条微博评论,突破15页限制!
目录 一.爬取目标 二.展示爬取结果 三.爬虫代码 四.同步视频 五.获取完整源码 您好,我是@马哥python说,一枚10年程序猿. 一.爬取目标 前些天我分享过一篇微博的爬虫: 马哥python说 ...