redis-geek-03-AOF日志-宕机了如何避免数据丢失
AOF日志-宕机了如何避免数据丢失
AOF⽇志正好相反,它是写后⽇志,“写 后”的意思是Redis是先执⾏命令,把数据写⼊内存,然后才记录⽇志
好处:
为了避免额外的检查开销,Redis在向AOF⾥⾯记录⽇志的时候,并不会先去对这些命令进⾏语法检 查。所以,如果先记⽇志再执⾏命令的话,⽇志中就有可能记录了错误的命令,Redis在使⽤⽇志恢复数据 时,就可能会出错。⽽写后⽇志这种⽅式,就是先让系统执⾏命令,只有命令能执⾏成功,才会被记录到⽇志中,否则,系统就 会直接向客⼾端报错。所以,Redis使⽤写后⽇志这⼀⽅式的⼀⼤好处是,可以避免出现记录错误命令的情况。
它是在命令执⾏后才记录⽇志,所以不会阻塞当前写操作
潜在风险:
如果刚执⾏完⼀个命令,还没有来得及记⽇志就宕机了,那么这个命令和相应的数据就有丢失的⻛险。
AOF虽然避免了对当前命令的阻塞,但可能会给下⼀个操作带来阻塞⻛险。这是因为,AOF⽇志也是 在主线程中执⾏的,如果在把⽇志⽂件写⼊磁盘时,磁盘写压⼒⼤,就会导致写盘很慢,进⽽导致后续的操作也⽆法执⾏了。
三种写策略
AOF机制给我们提供了三个选择,也就是AOF配置项 ...
redis-geek-02-高性能IO模型-为什么单线程redis那么快
为什么单线程redis那么快
我们通常说redis是单线程的,主要指redis的网络IO和键值对读写是由一个线程完成的,这也是redis对外提供键值存储服务的主要流程,但Redis的其他功能,⽐如持久化、 异步删除、集群数据同步等,其实是由额外的线程执⾏的
Redis的单线程设计机制以及多路复⽤机制
redis为什么要用单线程?
多线程的开销
多线程编程面临共享资源并发访问控制问题,⼀个关键的瓶颈在于,系统中通常会存在被多线程同时访问的共享资源,⽐如⼀个共享的数据结构。当有多个线程要修改这个共享资源时,为了保证共享资源的正确性,就需要有额外的机制进⾏保证,⽽这个额外的机制,就会带来额外的开销。
redis为什么这么快
redis的大部分操作在内存中完成,再加上采用了高效的数据结构例如哈希表和跳表
redis采用了多路复用机制,使其在⽹络IO操作中能并发处理⼤量的客⼾端请求,实现⾼吞吐率。
基于多路复用的高性能IO模型
在redis只运行单线程的情况下,该机制允许内核中,同时存在多个监听套接字和已连接套接字,内核会一直监听这些套接字上的连接请求和数据请求,一旦请求 ...
redis-geek-01-数据结构-一个键值数据库中包含哪些数据结构
数据结构
Redis中包含的数据类型
String(字符串)、List(列表)、Hash(哈希)、Set(集合)、Sorted Set(有序集合)
问题:
这些数据结构都是值的底层实现,键和值本⾝之间⽤什么结构组织?
给哈希表2分配更⼤的空间,例如是当前哈希表1⼤⼩的两倍
把哈希表1中的数据重新映射并拷⻉到哈希表2中
释放哈希表1的空间
这个过程看似简单,但是第⼆步涉及⼤量的数据拷⻉,如果⼀次性把哈希表1中的数据都迁移完,会造成Redis线程阻塞,⽆法服务其他请求。此时,Redis就⽆法快速访问数据了。 为了避免这个问题,Redis采⽤了渐进式rehash。
简单来说就是在第⼆步拷⻉数据时,Redis仍然正常处理客⼾端请求,每处理⼀个请求时,从哈希表1中的第⼀个索引位置开始,顺带着将这个索引位置上的所有entries拷⻉到哈希表2中;等处理下⼀个请求时,再顺带拷⻉哈希表1中的下⼀个索引位置的entries
为什么集合类型有那么多的底层结构,它们都是怎么组织数据的,都很快吗?
集合类型的底层数据结构主要有5种:整数数组、双向链表、哈希表 ...
leetcode-611. 有效三角形的个数
611. 有效三角形的个数
123456789101112131415161718192021222324252627282930class Solution { public int triangleNumber(int[] nums) { int ans = 0; // 先排序 Arrays.sort(nums); int n = nums.length; for (int i = 0; i < n; i++) { for (int j = i+1; j < n; j++) { // 只需要a+b>c即可 int a = nums[i]; int b = nums[j]; // 二分查找j+1~n-1的范围内符合条件的数据,使用二分查找 int l = j+1; ...
leetcode-21. 合并两个有序链表
21. 合并两个有序链表
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode() {} * ListNode(int val) { this.val = val; } * ListNode(int val, ListNode next) { this.val = val; this.next = next; } * } */class Solution { public ListNode mergeTwoLists(ListNode l1, ListNode l2) { if(l1 == n ...
leetcode-443. 压缩字符串
443. 压缩字符串
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758class Solution { public int compress(char[] chars) { int n = chars.length; int[] parent = new int[n]; for(int i = 0; i < n; i++){ parent[i] = i; } for(int i = 1; i < n; i++){ char ch = chars[i]; if(ch == chars[i-1]){ union(i, i-1, parent); ...
leetcode-128. 最长连续序列
128. 最长连续序列
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960class Solution { public int longestConsecutive(int[] nums) { // 并查集 int n = nums.length; int[] parent = new int[n]; Map<Integer, Integer> map = new HashMap<>(); // 初始化并查集 for(int i = 0; i < n; i++){ parent[i] = i; if(map.containsKey(nums[i])){ continu ...
leetcode-1893. 检查是否区域内所有整数都被覆盖
1893. 检查是否区域内所有整数都被覆盖
1234567891011121314151617class Solution { public boolean isCovered(int[][] ranges, int left, int right) { for(int[] arr : ranges){ int l = arr[0]; int r = arr[1]; if(left >= l && left<= r){ if(r >= right){ return true; } if(isCovered(ranges, r+1, right)){ return true; } ...
leetcode-1049. 最后一块石头的重量 II
1049. 最后一块石头的重量 II
123456789101112131415161718192021222324252627282930class Solution { public int lastStoneWeightII(int[] stones) { int n = stones.length; // 总重量 int sum = 0; for(int i = 0; i < n; i++){ sum += stones[i]; } // 想要返回石头的重量最小,则需要能达到的被摧毁的最大,最理想的结果是为0,假设为0是能达到的情况 int neg = sum/2; boolean[][] dp = new boolean[n+1][neg+1]; dp[0][0] = true; for(int i = 1; i <= n; i++){ ...