Redis网络模型
主从复制原理[*]建立毗连
[*]从节点在配置了 replicaof 配置了主节点的ip和port
[*]从库实验replicaof 并发送psync下令
[*]同步数据到从库
[*]主库bgsave生成RDB文件,并发送给从库,同时为每一个slave开辟一块 replication buffer 缓冲区记载从生成rdb文件开始收到的全部写下令。
[*]从库清空数据并加载rdb
[*]发送新写的下令给从库
[*]从节点加载 RDB 完成后,主节点将 replication buffer 缓冲区的数据(增量写下令)发送到从节点,slave 接收并实验,从节点同步至主节点雷同的状态。
[*]基于长毗连传播
[*]方便后续下令传输,除了写下令,还维持着心跳机制
网络模型
[*]壅闭IO
[*]非壅闭IO
[*]没啥用,还是需要等待数据准备就绪
[*]IO多路复用
[*]信号驱动IO
[*]异步IO
IO多路复用
文件描述符:简称FD
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/55c85d58924643feafd9452292adcbc6~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1459&h=857&s=115579&e=png&b=fefefe
select
流程:
[*]创建fd_set rfds
[*]假设要监听的fd为1,2,5
[*]实验select(5+1,null,null,3)
[*]第一个参数为最大长度+1,后面是等待时间
[*]内核遍历fd
[*]没有数据,休眠
[*]等待数据就绪或者超时
[*]遍历fd_set 找到就绪的数据
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/38004d867abe4d9b91447425491df8aa~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=3012&h=568&s=237289&e=png&b=ffffff
存在的标题
[*]需要将整个fd_set从用户空间拷贝到内核空间,select竣事后还要拷贝回用户空间
[*]需要遍历一次
[*]最大为监听1024
poll
将数据改为了链表,还是需要遍历
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d612a5f5e1cc4c5fa5e9d1435193734b~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=1676&h=772&s=503348&e=png&b=faf9f8
epoll
[*]epoll_create 创建epoll实例
[*]epoll_ctl 添加需要监听的fd,关联callback
[*]epoll_wait 等待fd就绪
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6703a3516ef543e1aa7420124683a86d~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=2790&h=1664&s=309563&e=png&b=fefdfd
epoll_wait有两种通知模式
[*]levelTriggered 简称LT 当FD有数据可读的时间,会重复通知多次,直到数据处理完成。是epoll的默认模式
[*]EdgeTriggered 简称ET 。当FD有数据可读的时间只会被通知一次,不管数据是否处理完成
ET模式避免了LT的惊群效应。
ET模式最好结合非壅闭IO。
镌汰策略
分类:全体,ttl
LRU
抽样LRU 不是严酷的
LFU
RedisObject中使用逻辑访问次数
访问频率越高,增长的越小,还会衰减(16位记载时间,8位记载逻辑访问次数)
总结
https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e3fe942a4c454c728cc9bcc1d96a6843~tplv-k3u1fbpfcp-jj-mark:0:0:0:0:q75.image#?w=5368&h=3343&s=827389&e=png&b=fffefe
附带的tcp毗连redis客户端 使用go编写的
package mainimport ( "bufio" "errors" "fmt" "io" "net" "strconv")// RedisClient 封装用于毗连type RedisClient struct { conn net.Conn //包装一层 方便读写 writer *bufio.Writer reader *bufio.Reader}func main() { //毗连redis conn, err := net.Dial("tcp", "127.0.0.1:6379") if err != nil { fmt.Println("毗连redis失败", err) } client := RedisClient{conn: conn, writer: bufio.NewWriter(conn), reader: bufio.NewReader(conn)} defer client.conn.Close() //发送下令 client.sendRequest([]string{"set", "name", "方块"}) //zrange boards:2024-4 0 -1 //client.sendRequest([]string{"zrange", "boards:2024-4", "0", "-1"}) //LRANGE tlist 0 -1 client.sendRequest([]string{"LRANGE", "tlist", "0", "-1"})}func (client *RedisClient) sendRequest(args []string) interface{} { length := len(args) firstCommand := fmt.Sprintf("%s%d", "*", length) client.writeCommand(firstCommand) for _, s := range args { n := len(s) client.writeCommand("$" + strconv.Itoa(n)) client.writeCommand(s) println(n, s) } response := client.handleResponse() //fmt.Printf("%v", response) return response}// 写下令func (client *RedisClient) writeCommand(s string) { client.conn.Write([]byte(s + "\r\n"))}// 解析返回结果func (client *RedisClient) handleResponse() interface{} { //先读取第一个字符 r, _, _ := client.reader.ReadRune() flag := string(r) fmt.Println("第一个操作数:" + flag) switch flag { case "+": //一行字符串 return client.ReadLine() case "-": //异常 return client.ReadLine() case ":": //数字 line := client.ReadLine() res, _ := strconv.Atoi(line) return res case "$": // 多行字符串 //readRune, _, _ := client.reader.ReadRune() //去掉换行 readRune := client.ReadLine() length := string(readRune) if length == "-1" { return nil } else if length == "0" { return "" } lll, _ := strconv.Atoi(length) //+2是跳过\r\n bytes := make([]byte, lll+2) n, _ := client.reader.Read(bytes) return string(bytes[:n]) case "*": //多行字符串 递归获取 return client.readBulkString() default: return errors.New("错误") }}// 读一行func (client *RedisClient) ReadLine() string { bytes, _, _ := client.reader.ReadLine() return string(bytes)}// 读到末尾 估计有点标题func (client *RedisClient) ReadToEnd() string { var size = 1024 bytes := make([]byte, size) var temp = "" for { n, err := client.reader.Read(bytes) temp += string(bytes[:n]) //n, err := client.conn.Read(bytes) if err == io.EOF || n == 0 || n < size { break } } return temp}func (client *RedisClient) readBulkString() interface{} { counts, _ := strconv.Atoi(client.ReadLine()) if counts
页:
[1]