1. redis网站 

Redis

Redis文档中心 -- Redis中国用户组(CRUG)

数据库排名网站:DB-Engines - Knowledge Base of Relational and NoSQL Database Management Systems

2. 基础知识

磁盘中的寻址速度是毫秒级,内存中寻址速度是纳秒级,在寻址上,磁盘比内存慢了10w倍

磁盘中,每个扇区是512字节

无论你读多少,操作系统都是最少从磁盘中拿4k

文件变大,磁盘io会成为瓶颈

数据库中有data page,大小是4k,和磁盘的读取大小一致

带宽:数据传输能力的大小

因为磁盘存储检索速度会变慢,内存存储价格比较昂贵,所以出现了缓存的概念,把少量数据存储在缓存中

3. 安装

1)下载

先去官网找到要下载的版本,例如:https://download.redis.io/releases/redis-6.2.7.tar.gz 

然后通过wget下载(也可以直接下载)

redis 位图查询_redis 位图查询

解压redis安装包 

tar -xf redis-6.2.7.tar.gz

 进入解压后的文件夹,其中有个README.md文件,可以查看这个文件进行操作

2)编译

make

redis 位图查询_redis 位图查询_02

3)启动

 执行src目录下的./redis-server命令,启动redis

./src/redis-server

redis 位图查询_数据库_03

安装redis到执行目录下

make install PREFIX=/root/redis/redis6

4)配置文件 

在/tec/profile文件中,加redis_home

vim /etc/profile

export REDIS_HOME=/opt/redis/redis6
export PATH=$PATH:$REDIS_HOME/bin

重新加载配置文件

source /etc/profile

这样,在任意位置都可以执行redis的命令了

5)添加实例

执行安装目录的utils目录下的install_server命令

./utils/install_server.sh

会出现端口号、文件地址、日志地址让选择,直接回车表示默认

redis 位图查询_缓存_04

 查看redis的状态(redis_6379 可以在/etc/init.d目录中查看)

service redis_6379 status

redis 位图查询_redis 位图查询_05

如果执行发生如下报错,

redis 位图查询_redis_06

 注释掉 install_server.sh中的相关代码

redis 位图查询_redis_07

 也可以继续在utils目录下执行install_server命令,启动更多的redis进程(实例)

redis 位图查询_数据库_08

6)连接redis

到安装路径下的bin目录中,执行

./redis-cli

4. redis相关小知识

redis是单进程、单线程、单实例的

epoll是Linux内核为处理大批量句柄而作了改进的poll

redis-cli:进入redis

redis-cli -h:查看帮助

redis默认有16个库

flushdb、flushall命令可以清库

help @String  查看string相关的命令

redis可以实现发布订阅功能:publish、subscribe

redis可以安装布隆过滤器的插件

5. IO

1.bio:同步阻塞io,read,write系统调用会阻塞,因此需要很多线程处理

2.nio:非阻塞io,同步非阻塞,但是需要循环多次进行系统调用read

3.同步非阻塞:select一次检测多个,循环read,但是需要在内核空间和用户空间来回拷贝

4.epoll:多路复用nio,依然是同步非阻塞io,因为虽然等待事件发生,但是依然需要自己调用read系统调用读取数据,先调用create创建一个注册器,ctl.add,del从注册器上新增或删除连接,wait等待连接产生事件,每次新链接绑定到注册器上,一次系统调用得到需要处理的socket,然后再循环处理有数据读写的socket连接

5.linux没有aio,windows的aio,read调用扔一个buffer到内核空间,内核读取数据到bugffer,完毕后通知用户线程进行操作

6. setNx和setXx

nx:不存在添加

xx:存在才能更新

7. 正反索引

正向的是 0、1、2...

反向的是-1、-2、-3...

8. 二进制安全

redis为了二进制安全,取的是字节流,

计算时,把字节流转换成数字

9. String

string:可以存字符串、数值、bitmap

bitmap的操作:setbit、bitcount、bitpos、bitop

10. List

list:链表,可以当做堆(同向操作)、队列(反向操作)、数组(lindex)、阻塞队列(BLPOP)

ltrim:删除队列两端的数据

11. Set

set可以做交并差集合操作

srandmember key count命令可以产生随机的列表(count是整数去重,负数不去重),可以用于抽奖

12. ZSet

zset:有序的,不可重复的;物理内存左小右大

可以进行交集、并集的集合操作(可以设置权重和聚合操作)

用skipList进行存储

13. 事务

multi:开启事务

discard:取消事务

exec:执行事务

watch:监控事务,如果监控的值被修改,事务不执行

先发送exec命令的先执行

通过管道实现事务

管道:将多个命令一次发送给服务器,降低通信成本

14. 缓存淘汰策略

redis可以设置内存大小,内存满了以后,执行淘汰策略

redis 位图查询_redis_09

LRU:最久使用

LFU: 最少使用

15. 过期时间

过期时间不会随着使用延长;

如果重新写值,并且没有给定过期时间,过期时间为-1(没有过期时间)

redis的key也可以定时过期

16. redis淘汰过期key

redis 位图查询_数据库_10

 

17. 管道

Linux中,| 是管道的意思,

作为衔接,前一个命令的输出作为后一个命令的输入

管道会触发创建子进程

父进程可以让子进程看到数据(export)

子进程的修改不会破坏父进程

父进程的修改也不会破坏子进程

18. RDB

RDB,通过fork创建子进程并拷贝副本,来将数据写入磁盘,写入的是时点数据;父进程对数据进行修改,子进程看不到父进程的修改;

父子进程的数据是隔离的

save:手动rdb

bgsave:在后台通过fork进行rdb

也可以在配置文件中设置rdb的时间

redis 位图查询_redis_11

 弊端:不是实时记录数据变化,可能会导致数据丢失

优点:恢复速度较快

19. AOF

缺点:体量大,恢复慢

优点:数据相对完整

4.0以前,会对aof日志进行重写,抵消部分日志,合并部分日志

4.0以后,会将rdb文件写到aof前面,将增量的操作以指令的方式写在后面

20. AKF

X:  增加副本,可以节点单点故障,读写分离

Y: 按照功能业务划分成多个进程

Z: 按照优先级、逻辑再拆分

21. 集群

强一致性可能会破坏可用性

主从:客户端可以访问主,也可以访问从

主备:客户端只访问主,当主挂了以后,备当主

集群一般使用奇数台,节省资源

replicaof:可以追随某个主节点,自己当从节点

redis通过哨兵和自动分区提供高可用

22. 哨兵,Sentinel

用于监控、提醒、自动故障转移

每个哨兵只知道主节点信息,通过发布订阅知道其他哨兵信息

23. 新增redis实例

新增redis实例可以解决数据量大的问题

可以根据业务或者逻辑来区分数据存放哪个redis,但是如果数据已经不能通过业务逻辑来区分的话

可以用hash+取模来决定数据放在哪个redis实例上,但是如果要增加redis实例的话,这种方式需要把所有数据重新算一下,再次存放

可以用一致性哈希算法,根据redis实例和数据来构成哈希环来解决所有数据都需要重新算的问题,但是这种,新增redis实例,会导致部分数据查询不到

redis 位图查询_redis 位图查询_12

 也可以通过代理层来解决访问redis实例

可以参考github中的twemproxy

也可以通过预分区的概念来选择访问redis实例(每个节点分几个hash值)

redis的cluster模式就是选用这种预分区的模式来进行redis实例选择,客户端先访问一个redis实例,然后进行hash计算,并且redis实例中有维护其他redis实例hash对应实例表,这样就可以返回这个key对应的是哪台redis实例。然后客户端再去访问对应的客户端

redis的连接成本很高,可以用nginx来解决

数据分布在不同的redis实例上以后,聚合操作、事务很难实现。可以人为的设置相同的前缀,然后用前缀来进行hash计算, {xx}k1,来实现需要进行聚合、事务操作的数据放进同一个redis实例上

24. 击穿

某个热点key过期,导致大量请求到了数据库

解决方案:

1. 设置热点key永不过期

2. 大量请求使用setnx分布式锁,只有获得锁的才能去请求数据库,并且将结果写入redis中,这样其他请求直接访问redis就好了

25. 穿透

大量请求某个不存在的key

解决方案:

1. 将不存在的key写入redis中,值为null

2. 使用布隆过滤器,也可以使用布谷鸟(支持删除的布隆过滤器)

26. 雪崩

大量热点key过期,导致大量请求到了数据库

解决方案:

1. 如果过期时间不是必须是相同的,可以设置随机的过期时间

2. 其他解决方案同击穿

27. 分布式锁

可以用setnx做分布式锁,但是

1. 如果加锁部分执行有问题,一直不释放锁怎么办

2. 加过期时间,过期时间设置多久合适,设置太短会导致业务代码没有执行完,锁就释放了,设置太长可能会导致阻塞住了

3. 使用多线程来监控加锁代码什么时候执行完,这样会增加代码复杂度

28. redis常用的客户端

Jedis:线程不安全

Lettuce:RedisClient ;线程安全的,可以同步

RedisTemplate:StringRedisTemplate可以解决key序列化问题

springboot整合redis时,需要对key和value进行序列化