深入理解Redis

redis配置文件全部说明

https://blog.csdn.net/love_yr/article/details/123338488

为什么出现Redis?

涉及到磁盘,io的知识

磁盘为什么慢?(高并发情况下增删改查都很慢,增加删除需要维护索引)

磁盘:

1,寻址:ms

2,带宽:G/M

内存:

1,寻址:ns

2,带宽:很大

秒>毫秒>微秒>纳秒 磁盘比内存在寻址上慢了10W倍

I/O buffer:成本问题

磁盘与磁道,扇区,一扇区 512Byte带来一个成本变大:索引

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

Redis和memcached的区别

都是key-value型数据库,区别在于value值是否区分类型

memcached:value值不区分类型,返回存的全部数据(可能是一个很大的json)给客户端,在客户端解析

redis:value值区分类型(6种类型),计算向数据移动(在数据存储的位置进行计算,只返回少量结果)

epoll基本原理(系统调用)

Epoll原理解析_~~ LINUX ~~-CSDN博客_epoll

select调用()

epoll调用(共享空间,红黑树,链表,epoll三函数)

redis二进制安全

redis服务端存数据时存的是字节数组  全部转换成字节数组写给客户端

redis  value值的五种类型

帮助命令

help

<group>

help @generic    

help @string

help @list

help @hash

help @set

help @sorted_set 

数据类型

字符串String  最大容量512M

列表list 使用双向循序链表实现(LinkedList)

散列 Hash 一般应用于将redis作为分布式缓存,存储数据库中的数据对象

集合set

有序集合zset 会自动排名,一般用于商品的排名

String数据类型的命令:

set:保存数据或修改数据: 例如 set name zhangsan

get 取数据   例如 get name

incr:递增 每使用一次   例如:incr age(可以用于年龄每年加一)

decr:递减 没使用一次           例如:decr age

incrby:增加 例如:incrby age 10 (如果age的值刚开始为20,执行命令后,值为30)

setbit          SETBIT mykey 7 1  第八位设置为1

bitcount        统计字符串被设置为1的bit数.       bitcount mykey

strlen        统计字节长度

1,有用户系统,统计用户指定时间段登录天数,且窗口随机

setbit sean 1 1
setbit sean 7 1
setbit sean 364 1
STRLEN sean
BITCOUNT sean -2 -1

bitpos         返回字符串里面第一个被设置为1或者0的bit位。

bitop        与或非 异或运算         示例:BITOP AND destkey srckey1 srckey2 srckey3 ... srckeyN

与运算:         有0则0,全1为1

或运算:         有1则1

非运算:         遇1取0,遇0取1

异或运算:      相同取0,不同取1

统计登录的用户人数,以日期为key,前面那个是以天数为key
setbit 20190101   1  1
setbit 20190102   1  1
setbit 20190102   7  1
bitop  or   destkey 20190101  20190102 //或运算
BITCOUNT  destkey  0 -1 //正反索引

hash数据类型的命令:

hset:存hash 例如: hset user1 name zhangsan 存user1的名字为zhangsan

hget 取hash 例如: hget user1 name取user1的名字

如果用户的属性字段太多的话这样存取很麻烦

hmset:存对象:hmset user1 name zhangsan password admin age 10 用户名为张三 密码为admin 年龄10

hmget:取对象 hmget user1 name age password

hgetall:取对象的所有属性的值 hgetall user2 取用户的所有信息

hdel:删除字段 hdel user2 name

 hincrbyfloat:          HINCRBYFLOAT mykey field 0.1   也可以用于统计次

list数据类型的命令

lpush:左存 例如:lpush key1 1 2 3 ;向key1集合中放入1,2,3三个数;

lrange:取值 例如 lrange key1 0 -1;取出key1 中所有的数据,命令格式:lrange 集合名称 开始索引 结束索引(结束索引为-1时取出所有的数据)

rpush:右存,例如:rpush key1 7 8 9 向key1中保存7,8,9

再取一次 lrange key1 注意一下格式

lpop:从左边弹出数据(删除最左边) 例如 lpop key1 弹出key1 集合的最上边的值

rpop:从右边弹出数据(删除最右边) 例如 rpop key1 弹出key1 集合最底部的值

左右各弹出一次,使用lrange key1 0  -1查询所有数据,显示如下:

set数据类型的命令(无序,不允许重复)

sadd :保存数据 例如sadd key1 1 2 3 4 5 向集合key1 中添加 1,2,3,4,5

smembers:查询数据 例如 smembers key1 查询key1 中的所有句酷

sismember:判断集合中是否存在某个元素 例如 sismember key1 10 判断集合key1中是否存在10 如果存在就返回1,不存在返回0;

sdiff:集合运算差集,例如sdiff key1 key2 求key1和kye2的差集 key1-key2

sinter:交集 例如 sinter key1 key2 求key1和key2的交集

sunion:并集 例如sunion key1 key2 求key1和key2的并集

srandmember: 取随机个数结果( 抽奖,投票)

spop:        随机弹出一个

zset数据类型的命令(有序集合,redis会自动排序)

适用于排行榜,排名

zadd:添加 例如 zadd zkey1 10 zhangsan 10 lisi 15 wangwu

zrange :查询(已经自动排序)

例如:zrange zkey1 0 -1 withscores(如果命令不带withscores则不会显示分数)

zrem:删除;例如zrem zkey1 wangwu 删除王五

zscore:查询单个分数 zsore zkey1 lisi 查询zkey1集合中lisi的分数

zrevrange:降序排序 例如: zrevrange zkey1 0 -1 withscores(命令中带有withscores则会显示分数)

交并差..

sorted_set 排序原理

  1. 跳跃表每层均是有序链表,最底层的链表为初始单链表。
  2. 类二分查找,结合了数组和链表的特点,查找、插入、删除时间复杂度为O(logn)。
  3. 跳跃表的层数与抛硬币策略有关,是一种随机化数据结构,每次运行结果都有所不同。

为什么用跳表而不用红黑树呢?猜想如下:
1)在做范围查找的时候,平衡树比skiplist操作要复杂。在平衡树上,我们找到指定范围的小值之后,还需要以中序遍历的顺序继续寻找其它不超过大值的节点。如果不对平衡树进行一定的改造,这里的中序遍历并不容易实现。而在skiplist上进行范围查找就非常简单,只需要在找到小值之后,对第1层链表进行若干步的遍历就可以实现。
2)平衡树的插入和删除操作可能引发子树的调整,逻辑复杂,而skiplist的插入和删除只需要修改相邻节点的指针,操作简单又快速。
3)从内存占用上来说,skiplist比平衡树更灵活一些。一般来说,平衡树每个节点包含2个指针(分别指向左右子树),而skiplist每个节点包含的指针数目平均为1/(1-p),具体取决于参数p的大小。如果像Redis里的实现一样,取p=1/4,那么平均每个节点包含1.33个指针,比平衡树更有优势。
4)查找单个key,skiplist和平衡树的时间复杂度都为O(log n),大体相当;而哈希表在保持较低的哈希值冲突概率的前提下,查找时间复杂度接近O(1),性能更高一些。所以我们平常使用的各种Map或dictionary结构,大都是基于哈希表实现的。
5)从算法实现难度上来比较,skiplist比平衡树要简单得多。
 

通用命令:

keys:返回满足给定pattern的所有key 例如keys *ad 查询所有以ad结尾的key

ping:检查服务器是否还活着,发一个ping,服务器会响应一个PONG

redis管道pipe

一次发送多个命令(没有客户端的情况下只要能联通redis也可以发送命令)

 redis发布订阅模式

订阅了同一个频道的客户端可以互发消息

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。
Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 client5 client1 之间的关系:

 聊天的逻辑()

发消息的时候和接收到消息的时候都要存

发消息的时候

接收到消息的时候

redis事务管理

原子性是数据库的事务中的特性。在数据库事务的情景下,原子性指的是:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。

对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。

Redis操作原子性的原因

事务队列  四个命令  不回滚

Redis的操作之所以是原子性的,是因为Redis是单线程的。

一个事务从开始到执行会经历以下三个阶段: 开始事务。命令入队。 执行事务。
redis以 MULTI 开始一个事务, 然后将多个命令入队到事务中, 最后由 EXEC 命令触发事
务, 一并执行事务中的所有命令:watch监听key ,key没有可以discard(撤销命令)
如果在多线程环境下:一个get key,一个删除key(删除的是key值,能得到nil),是否出错取决于谁先exec,而且redis出错并不回滚,而是继续执行剩下的命令

Redis过期

超时后只有对key执行DEL命令或者SET命令或者GETSET时才会清除。 这意味着,从概念上讲所有改变key的值的操作都会使他清除。 例如,INCR递增key的值,执行LPUSH操作,或者用HSET改变hash的field所有这些操作都会触发删除动作。

使用PERSIST命令可以清除超时,使其变成一个永久的key

Redis如何回收过期的keys

Redis keys过期有两种方式:被动和主动方式。

当一些客户端尝试访问它时,key会被发现并主动的过期。

当然,这样是不够的,因为有些过期的keys,永远不会访问他们。 无论如何,这些keys应该过期,所以定时随机测试设置keys的过期时间。所有这些过期的keys将会从密钥空间删除。

具体就是Redis每秒10次做的事情:

  1. 测试随机的20个keys进行相关过期检测。
  2. 删除所有已经过期的keys。
  3. 如果有多于25%的keys过期,重复步奏1.

这是一个平凡的概率算法,基本上的假设是,我们的样本是这个密钥控件,并且我们不断重复过期检测,直到过期的keys的百分百低于25%,这意味着,在任何给定的时刻,最多会清除1/4的过期keys。

redis数据持久化机制

9.1 什么是 Redis 持久化
由于 redis 的值放在内存中,为防止突然断电等特殊情况的发生,需要对数据进行持久化备份。即将内存数据保存 到硬盘。
9.2 Redis 持久化存储方式
9.2.1 RDB 持久化
RDB 是以二进制文件,是在某个时间点将数据写入一个临时文件,持久化结束后,用这个临时文件替换上次持久化
的文件,达到数据恢复。
优点:使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 redis 的高性能
缺点: RDB 是间隔一段时间进行持久化,如果持久化之间 redis 发生故障,会发生数据丢失。所以这种方式更适合
数据要求不严谨的时候
这里说的这个执行数据写入到临时文件的时间点是可以通过配置来自己确定的,通过配置 redis n 秒内如果超过
m key 被修改这执行一次 RDB 操作。这个操作就类似于在这个时间点来保存一次 Redis 的所有数据,一次快照
数据。所有这个持久化方法也通常叫做 snapshots
RDB 默认开启
9.2.2 AOF 持久化
Append-Only File ,将 操作 + 数据 以格式化指令的方式追加到操作日志文件的尾部,在 append 操作返回后 ( 已经写入到文件或者将要写入),才进行实际的数据变更, 日志文件 保存了历史所有的操作过程;当 server 需要数据 恢复时,可以直接 replay 此日志文件,即可还原所有的操作过程。 AOF 相对可靠, AOF 文件内容是字符串,非常 容易阅读和解析。
优点:可以保持更高的数据完整性,如果设置追加 fifile 的时间是 1s ,如果 redis 发生故障,最多会丢失 1s 的数 据;且如果日志写入不完整支持 redis-check-aof 来进行日志修复; AOF 文件没被 rewrite 之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的 flflushall )。
缺点: AOF 文件比 RDB 文件大,且恢复速度慢。
我们可以简单的认为 AOF 就是日志文件,此文件只会记录 变更操作 ”( 例如: set/del ) ,如果 server 中持续的大 量变更操作,将会导致 AOF 文件非常的庞大,意味着 server 失效后,数据恢复的过程将会很长;事实上,一条数 据经过多次变更,将会产生多条 AOF 记录,其实只要保存当前的状态,历史的操作记录是可以抛弃的;因为 AOF持久化模式还伴生了“AOF rewrite”
AOF 的特性决定了它相对比较安全,如果你期望数据更少的丢失,那么可以采用 AOF 模式。如果 AOF 文件正在被 写入时突然 server 失效,有可能导致文件的最后一次记录是不完整,你可以通过手工或者程序的方式去检测并修 正不完整的记录,以便通过 aof 文件恢复能够正常;同时需要提醒,如果你的 redis 持久化手段中有 aof ,那么在 server 故障失效后再次启动前,需要检测 aof 文件的完整性。 AOF 默认关闭,开启方法,修改配置文件 reds.conf appendonly yes

redis两种持久化的方式分别是什么原理

当前线程阻塞服务 不聊
异步后台进程完成持久
fork  +  cow

redis做缓存和做数据库的区别

 做数据库就要存储全量数据,内存不够用

做缓存:要尽可能利用redis内存空间,清除冷门key值,只存热数据,有以下六种策略主动清除未过期的key

Redis淘汰冷数据的策略

maxmemory-policy 六种方式(最大利用内存空间)

1、volatile-lru:只对设置了过期时间的key进行LRU(默认值) 

2、allkeys-lru : 删除lru算法的key   

3、volatile-random:随机删除即将过期key   

4、allkeys-random:随机删除   

5、volatile-ttl : 删除即将过期的   

6、noeviction : 永不过期,返回错误

Redis如何解决和数据库数据可能不一致的问题

首先明确:重要的数据不放缓存中,有以下几种解决方案

1.客户端先存redis,客户端再存mysql,redis挂了可能会丢数据

2.客户端先存mysql,客户端再存redis,这样会有2个问题:

  • 时间差,数据不一致(不重要也没关系)
  • 如果客户端挂了,redis数据没能更新,一直获取错误数据

3.客户端先存mysql,canal监听mysql数据有变化再存入redis,会有个时间差,如果绝对一致性要求,尝试让读取线程阻塞(牺牲可用性),等同步完继续运行

4.使用锁,防止缓存击穿,客户端先存mysql,删除缓存中的key,重新加载,也是有时间差

如何进行缓存预热?

1,提前把数据塞入redis,(你知道那些是热数据吗?肯定不知道,会造成上线很多数据没有缓存命中)
2,开发逻辑上也要规避差集(你没缓存的),会造成击穿,穿透,雪崩,实施456中的锁方案
3,一劳永逸,未来也不怕了
*,结合4,5,6点去看

单台redis的不足

单点故障

内存不足

压力过大

redis是单线程还是多线程?

1,无论什么版本,工作线程就是一个
2,6.x高版本出现了IO多线程
3,使用上来说,没有变化
------
3,[去学一下系统IO课],你要真正的理解面向IO模型编程的时候,有内核的事,从内核把数据搬运到程序里这是第一步,然后,搬运回来的数据做的计算式第二步,netty
4,单线程,满足redis的串行原子,只不过IO多线程后,把输入/输出放到更多的线程里去并行,好处如下:1,执行时间缩短,更快;2,更好的压榨系统及硬件的资源(网卡能够高效的使用);
*,客户端被读取的顺序不能被保障
那个顺序时可以被保障的:在一个连接里,socket里

redis存在线程安全的问题吗?为什么?

重复2中的单线程串行
redis可以保障内部串行
外界使用的时候要保障,业务上要自行保障顺序~!

主从复制相关知识

从redisreplicaof 主redis 会发生什么?分3种情况

1.从redis如果是第一次追随主redis且没开启applend only=yes,会把自己的数据清除,load主redis的rdb文件.

2.如果从redis之前已经和主redis连接过且没开启applend only=yes,则不会loadrdb文件,直接就可以获得增量更新后的数据,前提是红框内的大小放的下增量数据(主rdis内部维护了增量的数据,超过1mb就不行了,就得重新load)

3.如果从redis开启了aof的持久化方式(applend only=yes,),无论是否是第一次追随,都会重新load 主redis的rdb文件

相关配置说明

replica-serve-stale-data yes

当 replica 与 master 失去连接或者主从复制在进行时,replica 可以有两种不同的设置:

  • replica-serve-stale-data:yes(默认值),则 replica 仍将响应客户端请求,可能会有过期数据,或者如果这是第一次同步,则数据集可能为空。

  • replica-serve-stale-data:no , replica 将对所有请求命令(但不包含 INFO, replicaOF, AUTH, PING, SHUTDOWN, REPLCONF, ROLE, CONFIG, SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBLISH, PUBSUB, COMMAND, POST, HOST: and LATENCY)返回 SYNC with master in progress 的错误。

replica-read-only

可以将 replica 配置为是否只读,yes 代表为只读状态,将会拒绝所有写入命令;no 表示可以写入。从 Redis 2.6 之后, replica 支持只读模式且默认开启。可以在运行时使用 CONFIG SET 来随时开启或者关闭。

简述一下主从不一致的问题?

1,redis的确默认是弱一致性,异步的同步
2,锁不能用主从(单实例/分片集群/redlock)==>redisson
3,在配置中提供了必须有多少个Client连接能同步,你可以配置同步因子,趋向于强制一性
4,wait 2 0  小心
5,34点就有点违背redis的初衷了

如何解决redis容量不够的问题

如下图:两种解决方案:

1.对业务进行拆分,不同的业务连接不同的redis

2.数据不能再拆分,将数据分片放在不同的redis上(下图展示了三种分片机制)

 如何解决redis压力过大的问题

 解决办法1(代理)

解决方案2(代理+预分区)

3.redis使用的集群

每个节点维护了其他节点信息的映射,存值时也要先计算hash值,重定向存到相应的节点

 集群事务  {oo}

集群帮助命令

可以实现集群中节点中槽位整体的移动到另一个节点(reshard),查看信息info

CAP定理

未完待续....
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔◎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值