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 排序原理
- 跳跃表每层均是有序链表,最底层的链表为初始单链表。
- 类二分查找,结合了数组和链表的特点,查找、插入、删除时间复杂度为O(logn)。
- 跳跃表的层数与抛硬币策略有关,是一种随机化数据结构,每次运行结果都有所不同。
为什么用跳表而不用红黑树呢?猜想如下:
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事务管理
原子性是数据库的事务中的特性。在数据库事务的情景下,原子性指的是:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。
对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。
Redis操作原子性的原因
事务队列 四个命令 不回滚
Redis的操作之所以是原子性的,是因为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次做的事情:
- 测试随机的20个keys进行相关过期检测。
- 删除所有已经过期的keys。
- 如果有多于25%的keys过期,重复步奏1.
这是一个平凡的概率算法,基本上的假设是,我们的样本是这个密钥控件,并且我们不断重复过期检测,直到过期的keys的百分百低于25%,这意味着,在任何给定的时刻,最多会清除1/4的过期keys。
redis数据持久化机制
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定理