Redis(一)原理及基本命令(柔性数组)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis(一)原理及基本命令(柔性数组)



前言

Redis 是 Remote Dictionary Service 的简称,被称为远程字典服务;redis客户端和服务端是基于TCP建立网络通信的。

Redis 是内存数据库(保存在内存而不是磁盘),是目前市面上高性能的key-value数据库;底层的数据结构就是hash,因此查找数据的复杂度为O(1);

Redis属于非关系型数据库,用键值来存储。类似于哈希表数据结构。和MySQL这类关系型数据库是不一样的。


一、redis安装使用

安装

git clone https://gitee.com/mirrors/redis.git -b 6.2
cd redis
make
make test
make install

默认安装在 /usr/local/bin

redis-server 是服务端程序

redis-cli 是客户端程序

启动

mkdir redis-data
# 把redis文件夹下 redis.conf 拷贝到 redis-data # 修改 redis.conf
# requirepass 修改密码 123456
# daemonize yes
cd redis-data
redis-server redis.conf
# 通过 redis-cli 访问 redis-server
redis-cli -h 127.0.0.1 -a 123456

二、redis结构

redis是key-value的结构

key是字符串

value有几种常用的数据结构,如string、list、hash、set、zset

字符串string: 是一个安全的二进制字符串;

双端队列 (链表)list:有序(插入有序);

散列表 hash:对顺序不关注,由(field,value)组成,其中field 是唯一的;

无序集合 set:对顺序不关注,里面的值都是唯一的;

有序集合 zset:对顺序是关注的,里面的值是唯一的;根据 member来确定唯一;根据 score 来确定有序;

字符串

字符串定义

redis中的字符串是一种动态字符串。在C语言中字符串是以’\0’结尾的字符串数组。但在redis中是自己构建一套简单动态字符串(simple dynamic string 简称SDS)。

sds优点:

  • 降低获取字符串长度的时间
  • 避免缓冲区溢出(增加字符串字符采用扩容再拼接。普通字符串增加字符串的字符由于地址连续会覆盖后面的字符串)
  • 降低内存重分配次数(惰性空间释放和空间预分配) 二进制安全

redis源码中sds字符串数据结构:

struct __attribute__ ((__packed__)) sdshdr8 {
    uint8_t len; /* used */
    uint8_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr16 {
    uint16_t len; /* used */
    uint16_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};
struct __attribute__ ((__packed__)) sdshdr32 {
    uint32_t len; /* used */
    uint32_t alloc; /* excluding the header and null terminator */
    unsigned char flags; /* 3 lsb of type, 5 unused bits */
    char buf[];
};

sds中字符串分割是以长度len进行分割,不像C语言中字符串用\0做分割符,这样可以保存更多形式的数据。如文本数据,图片、音频、压缩文件等任意格式的二进制数据。

char buf[];是一个柔性数组。使用柔性数组的好处有两个:

1.不需要另起free,结构体free了柔性数组的空间就会释放。

2.初始化不占用空间。

3.申请的内存可以减少内存碎片化。

柔性数组详细内容参考什么是柔性数组

字符串特点

字符串是动态字符串,字符串长度小于1M 时,加倍扩容;超过 1M 每次只多扩 1M;字符串最大长度为 512M;

redis字符串是二进制安全字符串;可以存储图片,二进制协议等二进制数据;

字符串基础命令

# 设置 key 的 value 值
SET key val
# 获取 key 的 value
GET key
# 执行原子加一的操作
INCR key
# 执行原子加一个整数的操作
INCRBY key increment
# 执行原子减一的操作
DECR key
# 执行原子减一个整数的操作
DECRBY key decrement
# 如果key不存在,这种情况下等同SET命令。 当key存在时,什
么也不做
# SETNX 将key设置值为value,如果key不存在,这种情况下等同SET命令。 当key存在时,什么也不做。SETNX是”SET if Not eXists”的简写。
SETNX key value
# 删除 key val 键值对
DEL key
# 设置或者清空key的value(字符串)在offset处的bit值。
SETBIT key offset value
# 返回key对应的string在offset处的bit值
GETBIT key offset
# 统计字符串被设置为1的bit数.
BITCOUNT key

存储结构

字符串长度小于等于 20 且能转成整数,则使用 int 存储;

字符串长度小于等于 44,则使用 embstr 存储;

字符串长度大于 44,则使用 raw 存储;

应用场景

对象存储 累加器 分布式锁 位运算

双端队列 (链表)list

双向链表实现,列表首尾操作(删除和增加)时间复杂度 O(1) ;查找中间元素时间复杂度为O(n) ;

基础命令

# 从队列的左侧入队一个或多个元素
LPUSH key value [value ...]
# 从队列的左侧弹出一个元素
LPOP key
# 从队列的右侧入队一个或多个元素
RPUSH key value [value ...]
# 从队列的右侧弹出一个元素
RPOP key
# 返回从队列的 start 和 end 之间的元素 0, 1 2 负索引
LRANGE key start end
# 从存于 key 的列表里移除前 count 次出现的值为 value 的元素
# list 没有去重功能 hash set zset
LREM key count value
# 它是 RPOP 的阻塞版本,因为这个命令会在给定list无法弹出任何元素的时候阻塞连接
BRPOP key timeout # 超时时间 + 延时队列

应用场景

队列

阻塞队列

异步消息队列

获取固定窗口记录

hash

散列表,unordered_map 通过 key 快速索引 value;

基础命令

# 获取 key 对应 hash 中的 field 对应的值
HGET key field
# 设置 key 对应 hash 中的 field 对应的值
HSET key field value
# 设置多个hash键值对
HMSET key field1 value1 field2 value2 ... fieldn valuen
# 获取多个field的值
HMGET key field1 field2 ... fieldn
# 给 key 对应 hash 中的 field 对应的值加一个整数值
HINCRBY key field increment
# 获取 key 对应的 hash 有多少个键值对
HLEN key
# 删除 key 对应的 hash 的键值对,该键为field
HDEL key field

存储结构

节点数量大于 512(hash-max-ziplist-entries) 或所有字符串长度大于> 64(hash-max-ziplist-value),则使用 dict 实现;

节点数量小于等于 512 且有一个字符串长度小于 64,则使用ziplist 实现;

应用场景

存储对象

购物车

SET

集合;用来存储唯一性字段,不要求有序;

基础命令

# 添加一个或多个指定的member元素到集合的 key中
SADD key member [member ...]
# 计算集合元素个数
SCARD key
# SMEMBERS key
SMEMBERS key
# 返回成员 member 是否是存储的集合 key的成员
SISMEMBER key member
# 随机返回key集合中的一个或者多个元素,不删除这些元素
SRANDMEMBER key [count]
# 从存储在key的集合中移除并返回一个或多个随机元素
SPOP key [count]
# 返回一个集合与给定集合的差集的元素
SDIFF key [key ...]
# 返回指定所有的集合的成员的交集
SINTER key [key ...]
# 返回给定的多个集合的并集中的所有成员
SUNION key [key ...]

存储结构

元素都为整数且节点数量小于等于 512(set-max-intsetentries),则使用整数数组存储;

元素当中有一个不是整数或者节点数量大于 512,则使用字典存储;

应用场景

抽奖

共同关注

推荐好友

zset

有序集合;用来实现排行榜;它是一个有序唯一;

基础命令

# 添加到键为key有序集合(sorted set)里面
ZADD key [NX|XX] [CH] [INCR] score member [score member ...]
# 从键为key有序集合中删除 member 的键值对
ZREM key member [member ...]
# 返回有序集key中,成员member的score值
ZSCORE key member
# 为有序集key的成员member的score值加上增量increment
ZINCRBY key increment member
# 返回key的有序集元素个数
ZCARD key
# 返回有序集key中成员member的排名
ZRANK key member
# 返回存储在有序集合key中的指定范围的元素 order by id limit 1,100
ZRANGE key start stop [WITHSCORES]
# 返回有序集key中,指定区间内的成员(逆序)
ZREVRANGE key start stop [WITHSCORES]

存储结构

节点数量大于 128 或者有一个字符串长度大于 64,则使用跳表 (skiplist);

节点数量小于等于 128(zset-max-ziplist-entries)且所有字符串长度小于等于 64(zset-max-ziplist-value),则使用ziplist 存储;

数据少的时候,节省空间;O(n)

数量多的时候,提升访问性能;O(1)或者O(logn)

应用场景

百度热榜

延时队列

分布式定时器

时间窗口限流

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
8天前
|
NoSQL Redis 数据库
Redis的全局命令及相关误区
Redis的全局命令及相关误区
21 0
|
17天前
|
NoSQL Redis 数据库
Redis中的常用命令有哪些?
Redis常用命令包括:PING测试连接,ECHO回显,SELECT切换数据库,QUIT关闭连接;KEYS查找key,EXISTS检查存在,DEL删除key,EXPIRE设置过期时间,TTL查看剩余生存时间,TYPE检测数据类型;STRING操作如SET/GET/MSET/MGET,INCR/DECR增减计数;HASH命令如HSET/HGET/HMSET/HMGET/HGETALL管理字段;LIST操作如LPUSH/RPUSH/LPOP/RPOP/LRANGE;
9 0
|
2月前
|
存储 缓存 NoSQL
蚂蚁金服P7私藏的Redis原理与实践内部笔记
Redis 是完全开源免费的,是一个高性能的key-value类型的内存数据库。整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到硬盘上进行保存。因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value DB。
59 1
|
22天前
|
NoSQL Redis
Redis集群(六):集群常用命令及说明
Redis集群(六):集群常用命令及说明
15 0
|
2月前
|
缓存 NoSQL 数据处理
Redis事务悄然而至:命令的背后故事
Redis事务悄然而至:命令的背后故事
26 0
|
3月前
|
NoSQL Java 测试技术
字节二面:Spring Boot Redis 可重入分布式锁实现原理?
字节二面:Spring Boot Redis 可重入分布式锁实现原理?
158 1
|
1月前
|
存储 缓存 Java
【Spring原理高级进阶】有Redis为啥不用?深入剖析 Spring Cache:缓存的工作原理、缓存注解的使用方法与最佳实践
【Spring原理高级进阶】有Redis为啥不用?深入剖析 Spring Cache:缓存的工作原理、缓存注解的使用方法与最佳实践
|
1月前
|
缓存 NoSQL Java
【Redis】5、Redis 的分布式锁、Lua 脚本保证 Redis 命令的原子性
【Redis】5、Redis 的分布式锁、Lua 脚本保证 Redis 命令的原子性
56 0
|
8天前
|
运维 NoSQL 算法
Java开发-深入理解Redis Cluster的工作原理
综上所述,Redis Cluster通过数据分片、节点发现、主从复制、数据迁移、故障检测和客户端路由等机制,实现了一个分布式的、高可用的Redis解决方案。它允许数据分布在多个节点上,提供了自动故障转移和读写分离的功能,适用于需要大规模、高性能、高可用性的应用场景。
15 0
|
20天前
|
存储 NoSQL Redis
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)(三)
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)
19 0

热门文章

最新文章