Redis初学
1. Redis初识
- 全称 Remote Dictionary Server,远程字典服务,基于内存实现的键值型非关系数据库,由意大利人 Salvatore Sanfilippo 用C语言编写,遵守BSD协议,实现免费开源。
- 无新建数据库操作,自带16个数据库,默认使用0库。没有表的概念,通过不同的数据类型来实现存储数据的需求。
- 适用场景:Redis 用来缓存一些经常被访问的热点数据、或者需要耗费大量资源的内容,通过把这些内容放到 Redis 中,可以让应用程序快速地读取它们。
- 默认端口号6397,来源emmmmm
2. Redis的安装
2.1 在Ubuntu下安装Redis
$:sudo apt update
$:sudo apt install redis-server
#启动Redis服务端
redis-server
#启动Redis客户端
redis-cli#返回`redis 127.0.0.1:6379>`
#验证是否成功安装
redis 127.0.0.1:6379> ping#返回PONG
3. Redis配置
3.1 查看配置项
redis 127.0.0.1:6379> CONFIG GET 配置名称
,使用*查看所有项redis 127.0.0.1:6379> CONFIG GET *
3.2 更改配置项
通过使用CONFIG SET命令来修改配置项,
redis 127.0.0.1:6379> CONFIG SET 配置项名称 配置项参数值
3.3 更改配置文件
Redis有些配置信息无法通过命令行直接修改,则需要修改配置文件,比如允许远程连接的功能。
3.4 redis.conf 配置说明
配置项 | 参数 | 说明 |
---|---|---|
port | 6379 | 指定 Redis 监听端口,默认端口为 6379 |
bind | 127.0.0.1 | 绑定的主机地址 |
databases | 16 | 设置数据库的数量(0-15个)共16个,Redis 默认选择的是 0 库,可以使用 SELECT 命令来连接指定的数据库储存数据。 |
loglevel | notice | 指定日志记录级别,支持四个级别:debug、verbose、notice、warning,默认为 notice。 |
4. Redis数据类型
Redis是Key-Value类型缓存型数据库,支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
4.1 String字符串
4.1.1 简介
String类型是Redis最基本的类型,一个key对应一个value。Redis的String类型是二进制安全(binary safe)的,可以包含任何数据,例如图片或者序列化对象,最大能存储512MB,使用set、get命令来插入和读取数据。
#使用SET,GET方法为Redis数据库插入String类型数据和读取数据
redis 127.0.0.1:6379> set name min#存储一个key为name,value为min的String类型数据
#返回OK
redis 127.0.0.1:6379> get name#通过key获取value
#返回"min"
#使用MSET,MGET批量插入、读取数据
redis 127.0.0.1:6379> mset age 18 sex man#存储两个键值对,age:18,sex:man
#返回OK
redis 127.0.0.1:6379> mget age sex #m代表many
#返回 1)"18"
2)"man"
#删除key
redis 127.0.0.1:6379> del name
4.1.2 实现
Redis使用C语言编写,但并未使用C语言的字符类型,而是自定义了一个属于特殊结构SDS(Simple Dynamic String)简单动态字符串,是一个可修改的内部结构,类似于Java的ArrayList。
//SDS的结构定义
struct sdshdr{
//记录buf数组中已使用字符的数量,等于 SDS 保存字符串的长度
int len;
//记录 buf 数组中未使用的字符数量
int free;
//字符数组,用于保存字符串
char buf[];
String采用了预先分配冗余空间的方式来减少内存的频繁分配,Redis每次给String分配的空间都会大于字符串实际占用的空间,在一定程度上提高了存储的效率,比如当字符串长度变大时,无需再重新申请内存空间。
4.1.3 自动扩容
当字符串所占空间小于 1MB 时,Redis 对字符串存储空间的扩容是以成倍的方式增加的;而当所占空间超过 1MB 时,每次扩容只增加 1MB。Redis 字符串允许的最大值字节数是 512 MB。
4.1.4 Redis数值操作命令
Redis String类型提供了一些操作数值的命令,比如incrby自增,decrby自减,incy加1,decr减1,incrbyfloat浮点数加减等。使用场景:常见的点赞,取消点赞,关注,取消关注等操作。
127.0.0.1:6379> incr people #加1
(integer) 1
127.0.0.1:6379> decr people #减1
(integer) 0
127.0.0.1:6379> incrby people 5 #递增5
(integer) 5
127.0.0.1:6379> decrby people 4 #递减4
(integer) 1
127.0.0.1:6379> get people #1-1+5-4=1
"1"
4.1.5 Redis字符串常用命令汇总(不定期更新)
命令 | 作用 |
---|---|
set key value | 设定指定键的值 |
get key | 检索指定键的值 |
mset key1 value key2 value | 同时设置多个键值对 |
mget key1 key2 | 同时获取多个键的值 |
strlen key | 返回key对应value的字符串值的长度 |
getset key value | 将给定的key值设置成value,并返回上一个value |
incr key | 将key中存储的数字加1 |
decr key | 将key中存储的数字减1 |
incrby key increment | 将key所存储的值加上给定的递增值 |
decrby key decrement | 用key所存储的值减去给定的递减值 |
incrbyfloat key increment | 将key所存储的值加上或减去指定值(+,-) |
4.2 Hash散列
Hash散列是由String类型组成的field和value组成的映射表,可以理解为包含多个键值对的集合,一般用来存储对象,一个Hash包含2^32 - 1(40亿)键值对,使用hmset、hget来插入和读取数据。
#可以抽象成这种类型
(key,((field1:value1),(field2:value2),(field3,value3)))
redis 127.0.0.1:6379>hmset user1 name min age 18 sex man email 1234567@google.com#为user1存储了4个field=>value对
#返回OK
redis 127.0.0.1:6379>hgetall user1#获取user1所有的field=>value对
#返回
1) "name"
2) "min"
3) "age"
4) "18"
5) "sex"
6) "man"
7) "email"
8) "123456@google.com"
redis 127.0.0.1:6379>hget user1 name#获取user1的name值
#返回"min"
4.3 List链表
Redis List中的元素是字符串类型,按照插入顺序排序,允许重复插入,最多可插入2^32 - 1(40亿)个元素,可以添加一个元素到List的头部或尾部,遵循索引机制,使用lpush、lrange来插入和读取数据。
127.0.0.1:6379> lpush lanuage C #lpush key value
#返回(integer) 1
127.0.0.1:6379> lpush lanuage C++
#返回(integer) 2
127.0.0.1:6379> lpush lanuage Java
#返回(integer) 3
127.0.0.1:6379> lpush lanuage Python
#返回(integer) 4
127.0.0.1:6379> lpush lanuage Golang
#返回(integer) 5
127.0.0.1:6379> lpush lanuage Swift
#返回(integer) 6
127.0.0.1:6379> lrange lanuage 0 6 #lrange key start stop
#返回
1) "Swift"
2) "Golang"
3) "Python"
4) "Java"
5) "C++"
6) "C"
#第一个插入的在最后面,最后一个插入的在最前面,与队列相似。
4.4 Set无序集合
Redis Set是一个字符串类型元素构成的无序集合,通过哈希映射表实现的,添加、删除、查找元素的时间复杂度都为O(1)。Set集合中的成员具有唯一性,所以重复插入元素不会成功,第二次插入的元素将被忽略。使用SADD、SMEMBERS命令来插入和读取数据。
127.0.0.1:6379> sadd animal lion #sadd key member,添加成功返回1,失败返回0
#返回(integer) 1
127.0.0.1:6379> sadd animal lion
#返回(integer) 0
127.0.0.1:6379> sadd animal dog
#返回(integer) 1
127.0.0.1:6379> sadd animal cat
#返回(integer) 1
127.0.0.1:6379> sadd animal tiger
#返回(integer) 1
127.0.0.1:6379> sadd animal monkey
#返回(integer) 1
127.0.0.1:6379> sadd animal horse
#返回(integer) 1
127.0.0.1:6379> smembers animal #smembers key,查看集合中元素,元素无序排列
#返回
1) "cat"
2) "tiger"
3) "lion"
4) "dog"
5) "monkey"
6) "horse"
4.5 ZSet有序集合
Redis ZSet是由字符串类型构成的有序集合,集合中的元素具有唯一性,并且每个元素还会关联一个Double类型的分数,该分数允许重复,Redis正是同个这个分数来为集合中的元素进行从小到大排序的。使用zset和zrange命令来插入和读取数据。
#这里Linux打错了,type key的时候发现的,裂开。
127.0.0.1:6379> zadd Liunx 0 ubuntu #zadd key score member,插入元素,成功return1,失败return0
(integer) 1
127.0.0.1:6379> zadd Liunx 1 centOS
(integer) 1
127.0.0.1:6379> zadd Liunx 2 Fedora
(integer) 1
127.0.0.1:6379> zadd Liunx 3 Debian
(integer) 1
127.0.0.1:6379> zadd Liunx 3 Mint
(integer) 1
127.0.0.1:6379> zrange Liunx 0 3 #查找zset中所有的元素
1) "ubuntu"
2) "centOS"
3) "Fedora"
4) "Debian"
127.0.0.1:6379> zscore Liunx centOS #查找指定元素的分数
"1"
4.6 bitmap位图
用来存储bool类型数据,同样属于String数据类型,用位来实现存储,通过将比特位设置为 0 或 1来达到数据存取的目的,本质上是一个普通的字节串,也就是一个bytes数组,使用
getbit/setbit
来操作位数组。
#存储h和e对应的八进制位数字
#h'0b1101000',e'0b1100101'
#1的下标:1、2、4、9、10、13、15
27.0.0.1:6379> setbit a 1 1
(integer) 0
127.0.0.1:6379> setbit a 2 1
(integer) 0
127.0.0.1:6379> setbit a 4 1
(integer) 0
127.0.0.1:6379> get hello
(nil)
127.0.0.1:6379> get a
"h"
127.0.0.1:6379> setbit a 9 1
(integer) 0
127.0.0.1:6379> setbit a 10 1
(integer) 0
127.0.0.1:6379> setbit a 13 1
(integer) 0
127.0.0.1:6379> setbit a 15 1
(integer) 0
127.0.0.1:6379> get a
"he"
127.0.0.1:6379> bitcount a
(integer) 7
使用场景:bitmap适用于一些用户签到次数,登录次数等场景,相比于使用字符串,使用bitmap大大降低了内存空间的使用率。统计用户一年的登录次数,使用字符串就需要365个键值对,若使用位图,则登录存1,未登录存0,不仅效率高还节省内存。
命令 | 作用 |
---|---|
getbit key bit | 获取某一位上的值 |
bitcount key start stop | 统计某一区间上1的数量 |
setbit key offset value | 设置或清除某一位上的值,其返回值是原来位上存储的值 |
4.7 HyperLogLog基数
Redis HyperLogLog数据类型是用来做基数统计的的算法,Redis 2.8.9 版本中的新增类型,在输入的元素的数量或体积非常大时,计算基数所需的空间总是固定的,而且是很小的,因为HyperLogLog只会根据输入元素来计算基数,而不会存储并返回基数本身。(基数:数据集中不重复的元素的数量)
使用场景:统计网站月活动量,UV网站独立访客(不重复)
127.0.0.1:6379> pfadd user user1 user2 user3#向user中插入元素
(integer) 1
127.0.0.1:6379> pfcount user#统计user的基数
(integer) 3
127.0.0.1:6379> pfadd manager manager1 manager2#向manager中插入元素
(integer) 1
127.0.0.1:6379> pfcount manager#统计manager的基数
(integer) 2
127.0.0.1:6379> pfcount user manager#统计user和manager的基数
(integer) 5
127.0.0.1:6379> pfmerge all user manager#将user和manager合并为一个key(all)
OK
127.0.0.1:6379> pfcount all#统计合并后的的基数
(integer) 5
5. Redis命令
本地服务器上运行命令:
redis-cli
,启动Redis客户端
远程服务器上运行命令:
redis-cli -h host -p port -a password
,示例:redis-cli -h 192.168.6.1 -p 6379 -a 123456
参数说明:
- -h:用于指定远程 Redis 服务器的 IP 地址;
- -p:用于指定 Redis 远程服务器的端口号;
- -a:可选参数,若远程服务器设置了密码,则需要输入。
6. Redis键(key)
Redis键命令用来管理Redis的键
语法:COMMAND KEY_NAME
6.1 Key的类型
Key的类型对应着Value的数据类型,同样也有五种数据类型。可以通过TYPE命令来查看Key的数据类型。
127.0.0.1:6379> type name
string
127.0.0.1:6379> type user1
hash
127.0.0.1:6379> type lanuage
list
127.0.0.1:6379> type animal
set
127.0.0.1:6379> type Liunx
zset
6.2 Key的命名规范
Key的命名不能过长也不能过短,过长影响查询效率并且浪费内存空间,过短影响可读性,Redis建议“见名知意”的命名规范。
6.3 Key的过期时间
- 意义:Redis允许为Key设置一个过期时间,即到点自动删除,一是可以避免使用频率不高的key长期存在,占用内存资源,再是控制缓存的实效时间。
- 处理方法:Redis将每个设置了过期时间的key单独存放到一个字典中,并定期遍历这个字典来删除过期的key。除此之外,还会使用惰性策略来删除过期的key,即当客户端访问这个key的时候,Redis对当前key的过期时间进行检查,如果过期了就立即删除。Redis运用这两种方法一起来处理过期时间。
- 运用场景:例如购物软件双十一活动,今年活动的数据到了明年就没有意义了,因此可以给key设置一个过期时间,从而减少无用资源占用内存资源。
6.4 Redis键命令汇总(不定时更新)
命令 | 作用 |
---|---|
del key | 若key存在,则删除 |
exists key | 检查key是否存在 |
type key | 获取value的数据类型 |
expire key | 设置key的过期时间,以秒为单位 |
ttl key | 检查key还有多久过期,以秒为单位 |
rename key | 修改key的名字 |
dump key | 用于将键对应的值进行序列化处理 |
keys * | 返回当前库中所有的键 |
7. Redis连接命令
Redis连接命令主要是用于验证Redis服务器的连接状态,检查服务器的状态。Redis通过Redis序列化协议(RESP)实现客户端和服务端的连接通信。
RESP协议:
- 网络模型:主要负责数据的交互组织方式
- 序列化协议:实现了数据的序列话
常用Redis测试连接命令汇总:
命令 | 作用 |
---|---|
auth password | 验证密码是否正确 |
echo message | 打印字符串 |
ping | 查看服务是否正常运行 |
quit | 关闭当前连接 |
select index | 切换到指定的数据库 |
#通过config命令配置客户端连接密码
127.0.0.1:6379> config set requirepass 676767
OK
127.0.0.1:6379> auth 676767 # 验证密码是否正确
OK
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> echo helloworld
"helloworld"
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> quit
parallels@parallels-Parallels-Virtual-Platform:~$
8. Redis安全策略
8.1 命令配置密码
使用
config set requirepass password
命令配置密码后,执行操作会报错,需要使用auth password
来进行密码验证。通过命令行配置的密码并非永久有效,当重启服务后密码就会失效。
127.0.0.1:6379> config get requirepass # 默认情况下,requirepass参数为空""
1) "requirepass"
2) ""
127.0.0.1:6379> config set requirepass 67
OK
127.0.0.1:6379> config get requirepass
1) "requirepass"
2) "67"
127.0.0.1:6379> auth 67
OK
8.2 手动配置密码
在安装目录中找到
redis.windows.conf
文件,Ctrl+F检索requirepass关键字,找到配置项并配置密码,修改配置文件需要重启服务器。重新启动后刚才配置的密码永久有效。
8.3 指令安全
Redis中有一些非常危险的命令,错误操作会带来严重的后果,例如keys *会是Redis卡顿,flushdb和flushall会清空数据库。
解决方法:
- Redis在配置文件中提供了rename-command命令来讲某些危险的命令修改为其他名称,从而避免人为失误操作。
- 示例:
rename-command flushall ""
8.4 端口安全
如果Redis服务器有外网地址,那么Redis服务器有可能被外网直接访问到,内部数据就丧失了安全性。
解决方法:
- 绑定要监听的IP地址,
bind 192.168.x.x
- 使用密码验证,
auth password
9. 客户端命令
Redis通过监听TCP端口的方式来接受客户端的连接,底层是一个单线程模型,采用IO多路复用技术,多个网络连接,复用同一个线程。Redis提供了一些客户端命令,可以轻松的实现对客户端的管理,控制。
一些常用命令:
命令 | 作用 |
---|---|
config get maxclients | 获取最大连接数,默认10000 |
config set max clients 15000 | 设置最大连接数 |
client list | 以列表形式返回所有连接到服务器的客户端 |
client setname | 设置当前连接名 |
client getname | 获取当前连接名 |
client id | 返回当前连接id |
10. Redis服务器命令
Redis服务器是对客户端提供服务的主体,安装了Redis数据库的计算机都可以通过本地或者远程对外提供服务。
一些常用命令:
命令 | 作用 |
---|---|
bgsave | 用异步的方式将Redis数据库的数据同步到磁盘中 |
command | 返回Redis命令的详细描述信息 |
command count | 用户获取命令的总数 |
info | 获取Redis服务器的各种信息和统计数值 |
dbsize | 返回当前数据库中键的总值 |
time | 返回当前服务器的时间 |
11. Redis发布订阅(PubSub)
Redis PubSub发布订阅模式,一种消息传播系统,实现了消息多播功能,发布者发布消息,订阅者接受消息,用来传递消息的链路被称作channel,一个客户端可以订阅任意的channel。
一些常用命令:
命令 | 作用 |
---|---|
subscribe channel | 订阅一个或多个频道 |
unsubscribe channel | 退订指定的频道 |
pulish channel message | 向指定频道发送消息 |
12. Redis消息队列(Stream)
13. 布隆过滤器(Bloom Filter)
Redis4.0的新功能,提供强大的去重功能,节省空间,但有1%的误判率。应用场景:海量数据去重,垃圾邮件过滤功能。