更新日志????
2022-10-06
Redis持久化
- RDB持久化
- AOF持久化
- 调整目录结构
2022-09-01
本次更新没有内容,就是调整一下目录结构。
2022-06-04 ????
- 新增
Redis
管理命令:trollface: - 新增
Redis
底层实现机制:trollface: - 新增配套脑图:trollface:
- 修正已知错别字词和问题描述:trollface:
2022-08-03????
- 修正已知错别字词句:trollface:
- 调整文章部分内容的格式:trollface:
2022-8-19????
- 新增Redis高级数据结构和功能部分内容
- Bitmap
- HyperLogLog
- GEO
- 事务、Lua脚本
- 发布订阅、Stream
- Pipeline流水线
- Redis模块
- 校对/修复文章内容
Redis简洁入门
关于
Redis
本身的一些语法、命令的使用。
简介
Redis
是一款基于键值对的NoSQL
数据库,它的值支持多种数据结构,比如,字符串,哈希,列表,集合,有序集合(sorted sets
)等。
Redis
将所有的数据都存放在内存中,所以它的读写性能方面堪称秀儿。同时,它还可以将内存中的数据以快照或日志的形式保存在硬盘上,以保证数据的安全性。
Redis
典型的应用场景包括:缓存、排行榜、计数器、社交网络、消息队列等等。
传送门:
官网
Windows版本下载
安装使用(Windows版本演示)
- 下载
msi
文件,点击安装,一路next
即可。 - 上一步完事之后将其添加到环境变量。
- 上一步完事之后打开黑窗口。
- 输入
redis-cli
回车。 - 如出现下图信息,表示安装成功并且服务以及启动。
简单使用
换库
代码语言:javascript复制默认内置了16个库(0-15) 切库命令:
select [索引]
命令
select 1
刷新
如果不需要之前的操作数据,执行
flushdb
可以将其刷掉。 命令 flushdb
字符串
- 存
以键值对的形式存储字符串形式的数据,如果需要存储以’-‘连接的字符串,用冒号【:】分隔。 示例:存储键为text-count,值为1的字符串。 set test:count 1
- 取
获取存储的字符串数据也很简单,一条
get
命令即可。 示例:取到key
为test:count
的value
。 get test:count 返回: "1"
- 改
redis
支持对存储的字符串数据进行一些基本的修改操作。 示例:将如上字符串加一、减一。 #加一 incr test:count #返回 2 #--------------------- #减一 decr test:count #返回 1
哈希
- 存
存储哈希的命令:
hset
由于哈希值本身也是kv的形式,所以需要两次进行key_value的输入。 示例:存于一个id为1,用户名为Tisox
的用户数据,名为【test-user】。 # 存入用户id hset test:user id 1 #提示:表示操作成功的提示 (integer) 1 #存入用户名 hset test:username Tisox #提示 (integer) 1 #------------------------------
- 取
和字符串存取类似,哈希的取值命令为
hget
示例:对上述存入的test-user信息进行读取。 #取id hget test:user id #返回 "1" #----------------------------------- #取用户名 hget test:user username # 返回 "Tisox"
列表
redis
里的列表比较特殊,它存储数据的方式可以从左右两边进行,可以视为一个横向的容器。 容器的左右两边都可以进行存取操作。并且列表是有序可重复的。
- 存
从左边存入:101 102 103 # 从左边存入101 102 103 lpush test:ids 101 102 103 # 提示 (integer) 3 # 查看其长度 llen test:ids # 返回 (integer) 3
- 查
列表支持不同的方式进行查看 # 按索引查看 lindex test:ids 0 # 返回 "103" lindex test:ids 2 # 返回 "101" # 按范围查看 lrange test:ids 0 2 # 返回 1) "103" 2) "102" 3) "101"
- 取
由于列表的特性,其取值也可以看作是队列或者栈的出队、出栈等操作。 # 从右侧弹出一个值 lpop test:ids #返回 "101" lpop test:ids #返回 "102"
集合
集合(sets),无序且不重复。
- 存
往集合中存入一个key为test-language ,值为
Java
,C
,Python
的数据。 # 存入 add test:language Java C Python # 提示 (integer) 3 # ----------------------------------- # 统计集合中有多少个元素 scard test:language # 返回 5 #------------------------------------ # 从集合中随机弹出一个元素:应用场景:【抽奖业务】 spop test:language # 返回 "Java" spop test:language # 返回 "Python"
- 查
查看集合中的元素 # 查看当前集合中的剩余元素 smembers test:language # 返回 "C " # 因为上面已经随机弹出了另外两个数据,所以就剩下了"Python"
有序集合(sorted sets)
给每一个存入的值附加一个分数,按照该分数进行排序的集合。
- 存
添加学生数据 # 添加学生以及其分数 zadd test:students 10 aaa 20 bbb 30 ccc 40 ddd 50 eee # 提示 (integer) 5 # 统计集合元素个数 zcard test:students # 返回 (integer) 5 # 查询某个值的分数 zscore test :students ccc # 返回 "30" # 返回目的按照分数排行(0、1、2、3、4.....) zrank test:students ccc # 返回 2 # 按照排序,取0-2大小的值 zrange test:students 0 2 # 返回 1) "aaa" 2) "bbb" 3) "ccc"
全局命令
代码语言:javascript复制字面意思,这些命令针对全局生效。
# keys *
keys *
# 返回
1) "test:user"
2) "test:language"
3) "text:count"
4) "test:ids"
5) "test:students"
# ----------------------------------
# keys test*
keys test*
# 返回
1) "test:user"
2) "test:language"
3) "text:count"
4) "test:ids"
5) "test:students"
# ------------------------------------
# 查看类型
type test:user
# 返回
hash
# 查看某个key是否存在
exists test:user
# 返回
1 #表示存在
# 输出key
del test:user
# ---------------------------------------
# 设置有效期:秒为单位,过期自动删除
expire test:students 10
管理 Redis
前面所有的命令都是基于key的基础上进行的,那么又怎样取管理和操作这些key呢?
以下是一些用来管理 key
的常用命令:这里只作一个列举,不会全部进行演示。
# 选择库
select index
代码语言:javascript复制index为redis库的索引,共有0-15个索引16个库,默认启用第一个库,索引为0。
# 查看全部的key
keys *
# 通过通配符进行匹配查看
# 查看所有key中以my开头的key
keys my*
代码语言:javascript复制注意,如果数据量很大的情况下,一般不建议直接使用
keys*
进行查看,该操作的时间复杂度是O(N),的,数据量太大可能会导致阻塞崩溃。
# 查看当前库中有多少key
dbsize
代码语言:javascript复制# 清理库中的key
flushdb
代码语言:javascript复制这是一个危险且强大的命令,如果使用不当,可能造成将所有的key全部删除,是不可逆的操作,在使用时应该三思。
# 查看key的数据类型
type key
代码语言:javascript复制# 判断某个key是否存在
exists key
代码语言:javascript复制# 随机返回一个key
randomkey
代码语言:javascript复制# 给key重命名
rename key newkey
代码语言:javascript复制建议在使用时结合
nx
参数使用。
# 删除一个或者多个key
del key1 key2 .....
# 或者
unlink key1 key2 ....
代码语言:javascript复制
del
带阻塞,unlink
则没有。
# 渐进式遍历key
# 基础用法,跟一个整数作为游标,表示从何处开始遍历
scan 0
# 进阶用法
scan 0 match counter* count 10
代码语言:javascript复制
counter*
表示匹配的规则,所有以该字符开头的key,count
后的数值表示每轮遍历的数量。为了方便演示
scan
的用法,我们需要有一定数量的key。可以使用redis
自带的压力测试工具来生成这些测试数据。 这个工具存在于/usr/bin/redisbenmark
。
# redisbenchmark的使用命令
redis-benchmark -c 5 -n 100 -r 1000 -a reids密码
上面的命令中:
5
表示启动的客户端数量100
表示请求数量1000
表示插入的数据量密码
表示你登录redis客户端的密码
以上就是 管理redis
部分的全部内容
Redis底层实现机制
Redis的对象体系
类型与编码
在redis中,每一种数据类型的底层都是由一种或者多种编码进行实现的,具体如下:
- String
int embstr raw
- list
ziplist linkedlist quicklist
- hash
ziplist hashtable
- set
intset hashtable
- zset
ziplist skiplist
可以看到,某一种编码可以同时应用在不同的数据类型的实现中。
查看类型编码
在前面有提到过一个命令:
代码语言:javascript复制type key
这是用来查看某个key的数据类型,这里的类型即指的是上面诸如 String,hash,set....
。而不能查看他们对应源码实现上所用的数据编码。可以通过下面的命令查看:
object encoding key
源码结构查看
具体的源码会在下一节中进行展开,这里介绍redis源码的结构。
数据结构 | 数据类型 | 数据库 | 服务端与客户端 | 其他 |
---|---|---|---|---|
动态字符串sds.c | 对象object.c | 数据库db.c | 事件驱动ae.c,ae_epoll.c | 主从复制replication.c |
压缩列表ziplist.c | 字符串t_string.c | 持久化rdb.c,aof.c | 网络连接anet.c,networking.c | 哨兵sentinel.c |
快速列表quicklist.c | 列表t_list.c | 服务端server.c | 集群cluster.c | |
整数集合intset.c | 哈希t_hash.c | 客户端redis-cli.c | 其他类型hyperloglog.c,geo.c | |
字典dict.c | 集合t_set.c | |||
有序集合t_zset.c |
简单动态字符串
概述
代码语言:javascript复制简单动态字符串(SDS),是
Simple Dynamic String
的缩写,是Redis
内部自定义实现的一种数据类型。在Redis
数据库内部,包含字符串的键值对在底层都是由SDS
实现的,它还被用于缓冲区的实现,如AOF
缓冲区、客户端的输入缓冲区。
set text "hello world"
rpush names "john" "lucy" "tony"
sadd users "liubei" "guanyu" "zhangfei"
诸如上面的类型,底层实现都用到了SDS.
学过或者了解过C语言的都知道,C语言它是有字符串这种数据类型的,那为什么 Redis
不是直接使用原生的字符串类型,而是自己自定义呢?
- C语言中,其实并没有实现意义上的字符串类型,而是将单个字符串储在
char
类型的数组中,进而来表示字符串。 - C语言用空字符