变强日记0

本文转自我的独立博客,更多精彩内容可访问我的独立博客

之所以开这个分类,是因为感觉自己的博客都是些读书笔记,大多都是知识点的摘抄,缺乏总结,也没有把知识点串起来。每天分析一个面试题问题,一个算法题,也算是对自己成长的记录吧。也希望自己能像这个分类的名字一样“变强”。

主要内容

  1. Redis为什么这么快
  2. 动态规划求字符串的最长回文子串

Redis为什么这么快

看牛客网上的分享,许多老哥都遇到过这个问题。想要回答好这个问题,需要系统的了解Redis的原理才行,刚好前段时间拜读了《Redis设计与实现》,虽然看完了书,但是想要系统的回答还是挺难的。

Redis之所以快,主要有以下几个方面的原因:

  1. 完全基于内存
  2. 简洁高效的数据结构设计
  3. 采用单线程,避免了不必要的上下文切换和竞争条件
  4. 使用了多路复用IO,非阻塞IO。
  5. Redis自己构建了VM机制来提高效率

基于内存

这一点很好理解,Redis处理的许多请求都是直接内存操作的,内存的读写速率显然是要比磁盘高很多倍的,

简洁高效的数据结构设计

Redis在底层实现上使用了许多设计精妙的数据结构,来提高效率。
比如Redis的字符串类型的底层实现使用的SDS,它可以常数复杂度获取字符串长度,空间预分配、惰性空间释放来提高效率。又比如使用跳跃表来实现快速访问节点和进行范围操作。
而且每个Redis中每个数据库对象(RedisDB)中都维护了一个字典(dict)来保存数据库中的所有键值对。类似于HashMap,其查找和操作的时间复杂度都为O(1)
KxTlpd.png

采用单线程

Redis为什么使用单线程,官方的解释是Redis的性能瓶颈不在CPU,最有可能的性能瓶颈在于机器的内存和网络带宽。而且单线程也符合Redis简洁的设计风格。
强调单线程是指在处理网络请求的时候只有一个线程,在其它时候也是不只一个线程的
详细原因:

  1. 不需要要各种锁的性能消耗
    Redis中有一些复杂的数据结构如list,hash等结构复制的数据结构,当需对这些复制的数据结构进行细粒度的操作的时候,如果不是单线程的话,就需要加很多的锁,导致同步的开销大大增加,但是使用单线程就不会存在这个我呢提。
  2. 降低了CPU的消耗
    多线程会到来上下文切换和竞争条件带来的开销,使用单线程就不会出现这样的问题。
  3. 可以使用单线程多进程的集群方案
    当CPU的性能成为瓶颈的时候,可以使用单线程多进程的集群方案来解决这个问题。
  4. 代码简洁
    使用单线程,代码将会变得简洁清晰,处理逻辑也更简单。

IO多路复用技术

Redis是单线程的,为了避免等待输入和输出带来的阻塞,redis使用了IO多路复用技术来解决这个问题。
Redis服务采用Reactor方式来实现文件事件处理器,每个网络连接都对应一个文件描述符。文件事件处理器使用IO多路复用模块同时监听多个套接字,每次套接字变为可应答,可写或者可读时,相应的文件事件就会产生。
KxODc4.png
当有多个文件事件并发出现的使用,IO多路复用程序会将所有产生事件的套接字放到一个队列里面。
KxO7DA.png

IO多路复用技术,中“多路”是指多个网络连接,“复用”是指复用一个线程。
复用技术可以让单个线程处理多个连接请求,提高了吞吐率。

VM机制

VM机制主要是为了避免内存不足而造成的访问速度下降的问题。Redis并没有使用操作系统实现的SWAP,而是自己实现的。
当数据多到内存放不下了,那就不可避免地会把冷数据放到磁盘中去,把热数据继续留到内存中。Redis通过自己实现地VM来提高了这一过程地效率。

Redis的作者对为什么不使用操作系统的VM而是使用自己实现的VM做出了以下的解释:

  1. OS是基于page(4k)的,而Redis对象大多都小于4k,因此OS提供的page方案对于Redis来说粒度太大了。如果使用OS的VM,那么一个页面上可能有多个Redis对象,另外比如list这种数据结构可能在多个页面上,这就导致哪怕只有很少的键被经常访问,当许多的页面都会被OS认为是活跃的,这样只有内存真正耗尽的时候OS才会交换页面。
  2. 相比于OS的交换方式,redis可以对交换到磁盘的对象进行压缩。
  3. OS交换的时候是会阻塞线程的,而redis可以让工作线程来完成交换,主线程继续处理请求。

动态规划求字符串的最长回文子串

思路:
若长度为L的字符串是回文,那么去掉首尾也是回文字符串。及全局最优解包含局部最优解。
最小子问题:

  1. 每个单独的字符组成的字符串是回文的
  2. 两个相邻的相同的字符串是回文。
class Solution {
    public String longestPalindrome(String s) {
        char[] chars=s.toCharArray();
        int len=s.length();
        if(len==0){
            return "";
        }
        if(len==1){
            return s;
        }
        int[][] dp=new int[len][len];
        int maxLen=1;
        int resIndex=0;

        //初始化矩阵,键最小子问题1的情况都设置为true
        for(int i=0;i<len;i++){
            dp[i][i]=1; //子问题一
            if((i<len-1)&&chars[i]==chars[i+1]){
                dp[i][i+1]=1; //子问题2
                resIndex=i;
                maxLen=2;
            }
        } 

       
        //从长度为3开始逐渐增长来检查回文字符串
        for(int L=3;L<=len;L++){
            for(int i=0;i<=len-L;i++){
                //如果字符串是回文的,那么首尾加上相同的字符也是回文的
                if(dp[i+1][i+L-2]==1&&chars[i]==chars[i+L-1]){
                    dp[i][i+L-1]=1;  //首尾加上相同的字符也是回文的
                    maxLen=L;
                    resIndex=i;
                }
            }
           
        }
        return new String(chars,resIndex,maxLen);

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值