03_Redis

文章目录

  • Redis
    • 介绍
    • 安装及使用
    • redis的核心配置
    • 数据结构
      • 常用命令
      • string
      • list
      • set
      • hash
      • zset(sortedset)
    • 内存淘汰策略
    • Redis的Java客户端
      • Jedis
      • Redisson

Redis

介绍

  • Redis是一个NoSQL数据库。
    • NoSQL: not only SQL。表示非关系型数据库(不支持SQL标准语法)。
  • 特点
    • C语言编写的
    • 开源的(https://github.com/redis)
    • 可基于内存:是把数据存在到内存上的
    • 可持久化:可以把内存里面的数据持久化到磁盘(为了实现数据恢复)
    • key-value:数据在内存中是以键值对的方式来存储的
    • 支持网络:客户端是通过网络连接服务端的
    • 支持多种语言:可以在各种语言的代码中操作Redis

安装及使用

  • 核心文件
    在这里插入图片描述
  • 启动
    • 启动服务器
      在这里插入图片描述
    • 启动客户端
      在这里插入图片描述
  • 在Linux系统中使用及安装
    在这里插入图片描述

redis的核心配置

  1. 常规配置
# 表示redis服务端是不是以守护进程(后台进程)的方式运行
daemonize no

# 客户端和服务端之间建立连接,假如超过多长时间没有进行通信那么就断开连接
# 0表示不关闭连接
timeout 0

# 端口号(一般不用去改)
port 6379

# 绑定的主机地址
bind 127.0.0.1
# 所有人都可以连接
# bind 0.0.0.0

# 日志级别
loglevel notice

# 数据库的数量设置
databases 16

# 密码设置
requirepass 123456
  1. 持久化配置
    • RDB
      • RDB是指Redis通过内存快照的形式来持久化内存中的数据到磁盘中。
        • 快照:其实就是一种内存技术,就可以像对内存进行拍照一样,保存内存当时的状态。
          • 快照的速度很快
          • 快照保存的一种数据的状态,占用的磁盘空间比较小
          • 快照会保存完整的数据
      • RDB是Redis默认的持久化策略,没有提供开关关闭。
    # 内存快照保存文件的位置
    dir D:\tmp
    
    # 内存快照保存文件的名字
    dbfilename dump.rdb
    
    
    # 快照触发的策略
    save <seconds> <changes>
    # 在多少秒之后,检查有多少次改变,如果达到设置的条件,那么就触发持久化
    save 900 1
    save 300 10
    save 60 10000
    
    • 总结:
      1. RDB每次保存的是触发RDB时刻的完整的数据
      2. RDB可能丢失数据,可能会丢失上一次持久化之后所有写入的数据
      3. RDB保存数据的速度很快,还原数据也很快
    • AOF
      • Append only file。AOF这种持久化的机制是通过追加(写操作命令)日志文件的方式来保存数据的
        • AOF会把用户输入的每一个写入命令保存到文件中,后续恢复数据的时候可以通过执行这个文件中的所有的命令来恢复数据。
      # 总开关
      # AOF默认是关闭的
      appendonly no
      
      # 保存文件的路径
      # 配置和RDB是同一个配置
      dir D:\tmp
      
      # 保存文件的名字
      appendfilename "appendonly.aof"
      
      # 保存的策略
      
      # 每收到一条写入的命令,就把命令保存到文件中
      # appendfsync always
      
      # 每秒保存一次(推荐使用的)
      appendfsync everysec
      
      # 依赖于操作系统的策略
      # appendfsync no
      
    • AOF持久化机制的总结:
      1. AOF可以做到不丢失数据(仅限于appendfsync always
      2. AOF保存数据生成的文件会越来越大,占用磁盘空间比较大
      3. AOF还原数据要通过 执行文件中的所有的命令来还原数据,还原数据比较慢
  • AOF和RDB是可以同时运行的。
    • 当两种机制都开启的时候,恢复数据的时候,优先从AOF生成的文件来恢复数据

数据结构

  • redis存储数据,支持五种数据结构
    • stringlisthashsetzset(sortedset)

常用命令

# 切换数据库(index从0开始)
select index

# 认证密码
auth password

# 搜索key (pattern 是一个正则表达式)
keys pattern
# 常用的是:keys * (查看所有的key)

# 清空数据库(删库)
# 清空所有的数据库(16个)
flushall

# 清空当前的数据库
flushdb

string

  • string数据结构是Redis中最基本的数据结构,包含 (String + 数字类型)
    在这里插入图片描述
# 设置一个键值对(如果key存在,会覆盖)
set key value

# 获取一个键值对的值
get key

# 批量的设置键值对
mset key1 value1 key2 value2 ...

# 批量的获取键值对
mget key1 key2 key3 ...

# 给指定的key的value +1 value必须得是一个数值
incr key

# 给指定的key增加指定的步长
incrby key increment

# 给指定的key的value -1
decr key

# 给指定的key减去指定的步长
decrby key decrement

# 设置一个key-value,并且指定过期时间
setex key seconds value

# set not exists,设置一个键值对,不会覆盖原来的值
# 当key不存在的时候,再去设值,不会覆盖原来的值
setnx key value

list

  • list的本质是一个双向链表。Redis支持用户从list的两端推入或者是弹出元素。
    • 可重复
    • 有序
      在这里插入图片描述
# 从队列的左端推入元素(当list不存在的时候,会自动创建一个新的list,然后来推入)
lpush key value1 value2 ...

# 从队列的左端弹出一个元素
lpop key

# 从队列的右端推入元素
rpush key value1 value2 ...

# 从队列的右端弹出一个元素
rpop key

# 查看链表的元素数量
llen key

# 查看某一个范围内的元素(start、stop指元素的下标,最左边的元素下标为0)
lrange key start stop

# 求指定下标的元素值
lindex key index

# 插入一个元素(在指定的元素pivot 前面或者是后面插入一个指定的元素 value )
# 如果指定的元素pivot有重复,那么就会在第一个值前面或者是后面插入
linsert key before|after pivot value

# 正常的从左端推入,当list存在的时候才会生效
lpushx key value

# 修改指定位置元素的值
lset key index value

# 删除前几个指定的元素
lrem key count value
  • 应用场景:
    • 消息队列
    • 最新动态(消息)排行榜

set

  • set是无序的集合
    1. 无序
    2. 不可重复
      在这里插入图片描述
# 往无序集合中添加元素
sadd key member1 member2 ...

# 查看无序集合中元素的个数
scard key

# 查看无序集合中所有的元素
smembers

# 判断某个元素在不在指定的集合中
sismember key member

# 随机弹出一个元素(取出并删除)
spop key [count]

# 随机从集合中取出一个元素的值(取出不删除)
srandmember key [count]

# 求交集
sinter key1 key2 ...

# 求出交集并保存
sinterstore destination key1 key2 ...

# 求并集
sunion key1 key2 ...

# 求出并集并保存
sunionstore destination key1 key2 ...

# 求差集
sdiff key1 key2 ...

# 求出差集并保存
sdiffstore destination key1 key2 ...

# 移动元素
smove source destination  member

# 删除元素
srem key member1 member2 ...
  • 应用场景:
    1. 求共同好友
    2. 好友推荐

hash

  • hash叫做二维表,类似于map。
  • hash这种数据结构可以看作是一个map,可以存储多个键值对。
    在这里插入图片描述
# 设置一个键值对
hset key field value

# 获取指定二维表中field的值
hget key field

# 设置多个键值对
hmset key field1 value1 field2 value2 ...

# 获取多个键值对的值
hmget key field1 field2 ...

# 判断二维表中有没有指定的field
hexists key field

# 获取二维表中所有的键值对
hgetall key

# 获取二维表中所有的键
hkeys key

# 获取二维表中所有的值
hvals key

# 求出二维表中 键值对的个数
hlen key

# 给键值对的值 增加指定的长度
hincrby key field increment

# 设置值,不覆盖
hsetnx key field value
  • 应用场景:
    • hash这种数据结构天然的适合存储对象,field存对象的成员变量名,value存成员变量对应的值
    • 存储商城中的购物车

zset(sortedset)

  • 有序的集合
    在这里插入图片描述
    • 有序集合的最大特点是:可以任意的取出有序集合中指定排名区间内的成员、以及指定分数区间内的成员
# 往有序集合中添加成员一级他的分数(注意:分数在前,名字在后)
zadd key score1 member1 score2 member2 ...

# 计算集合中元素的总个数
zcard key

# 求指定分数区间内成员的个数(分数是闭区间)
zcount key min max

# 求出指定成员的分数
zscore key member

# 给指定的成员增加分数
zincrby key score member

# 求出指定排名区间内的成员(排名从0开始,默认按照分数的升序排列)
zrange key start stop [withscores]

# 求出指定排名区间内的成员(排名从0开始,默认按照分数降序排列)
zrevrange key start stop [withscores]

# 求指定分数区间内的成员-按照分数的升序排列
zrangebyscore key min max [withscores]

# 求指定分数区间内的成员-按照分数的降序排列
zrevrangebyscore key max min [withscores]

# 求出指定成员的排名(按照分数的升序排名)
zrank key member

# 求出指定成员的排名(按照分数的降序排名)
zrevrank key member

# 删除指定的成员
zrem key member1 member2 ...

# 删除指定排名区间内的所有成员
zremrangebyrank key start stop [withscores]

# 删除指定分数区间内的所有成员
zremrangebyscore key min max [withscores]
  • 应用场景:
    1. 游戏中积分"排行榜"

内存淘汰策略

  • Redis是一个基于内存来存储的数据库,而内存资源是十分宝贵且有限的。那么当内存满了之后,Redis又需要存储新的数据的时候,Redis会触发内存淘汰策略,来淘汰老的数据,保证写入的成功。
  • 分类:
    • volatile-lru(least recent used)
      • 从已经设置了过期时间的数据集中,选择最近最少使用的数据进行淘汰
      • 比较合理的,但是比较慢
    • volatile-lfu
      • 从已经设置了过期时间的数据集中,选择一段时间内使用最少的key进行淘汰
    • volatile-random
      • 从已经设置了过期时间的数据集中,随机选择数据进行淘汰
      • 效率最高的
    • volatile-ttl
      • 从已经设置了过期时间的数据集中,选择最近将要过期的数据进行淘汰
    • allkeys-lru
      • 从所有的数据集中,选择最近最少使用的数据进行淘汰
    • alleys-random
      • 从所有的数据集中,随机选择数据进行淘汰
    • allkeys-lfu
      • 从所有的数据集中,选择一段时间内使用最少的key进行淘汰
    • no-evication
      • 禁止淘汰数据,如果有新的数据需要写入,那么就直接报错
  • 效率的角度出发:allkeys-random
    • 优先保证淘汰的效率
  • 合理性的角度从出发:volatile-lru

MySQL:

  1. 用户敏感的
  2. 访问量没那么大的

Redis:

  1. 用户不敏感的
  2. 访问量大的

Redis的Java客户端

Jedis

  • 全称叫做Java for Redis,使用非常简单,因为Jedis的每一个方法都和Redis的相关的命令名字是一致的。
  • 步骤
    • 导包
    <dependency>
    	<groupId>redis.clients</groupId>
    	<artifactId>jedis</artifactId>
    	<version>2.9.0</version>
    </dependency>
    
    • 配置
      • Jedis不需要任何配置
    • 使用
     // 1. 创建一个Jedis对象
        	Jedis jedis = new Jedis("localhost",6379);
    
     // 2. 认证密码
     		jedis.auth("123456");
    
     // 3. 操作
    		jedis.set("nickname", ls);
    		String nickname = jedis.get("nickname");
    		System.out.println(nickname);
    
    //        jedis.hset()
    //        jedis.rpush()
    //        jedis.sismember()
    //        jedis.zrank()
    //        jedis.zrevrank()
    

Redisson

  • 和Jedis不同,Redisson不仅仅实现了我们前面所学习过得所有的Redis命令对应的功能,它自己对Redis的功能做了很多的封装,提供了很多更为好用,更为强大的功能,比如基于Redis实现的分布式锁等等。
  • 步骤
    • 导包
    <dependencies>
        <dependency>
                <groupId>org.redisson</groupId>
                <artifactId>redisson</artifactId>
                <version>3.11.1</version>
        </dependency>
    </dependencies>
    
    • 首先构造出一个RedssonClient对象
    // 1. new 出一个config对象
         Config config = new Config();
         
    // 2. 配置Config对象
        SingleServerConfig serverConfig = config.useSingleServer()
                // 这里设置访问Redis的地址
                .setAddress("redis://localhost:6379")
                .setPassword("123456");
    
        // 设置序列化方式,使用jackson实现序列化和反序列化
        config.setCodec(new JsonJacksonCodec());
    
    // 3. 创建redis客户端 该对象在创建的时候,就会像redis-server发起连接请求
        RedissonClient redissonClient = Redisson.create(config);
    
    • 创建好RedissonClient对象之后,我们就可以基于ReidssonClient对象实现对Redis中5种基本数据类型的访问

eg:

/*
       该方法主要演示对于Redis,string类型数据的访问
   
   */ 
   private static void string(RedissonClient redissonClient) {
		/* 
		     1. number表示String类型的值对应的Redis中的key
		     2. 通过redissonClient获取存放key对应值的Bucket桶
		     3. 桶中放的就是key对应的Redis中的string类型的值
		     4. 对于桶的基本操作就是get/set,获取桶中的值/设置桶中的值
		     5. 对桶中值的操作都相当于是对Redis中key对应的string类型的值的操作
		 
         */
        RBucket<Integer> bucket = redissonClient.getBucket("number");
        bucket.set(0);

        // 获取对应的String数据类型的值
       Integer result = bucket.get();
        System.out.println(result);
       
        // 获取obj对应的存放String类型值的Bucket桶(这里其实对象被转化成了json字符串)
        RBucket<Person> personBucket = redissonClient.getBucket("obj");
        Person person = new Person();
        person.setName("ls");
        // 向桶中放入对象
        personBucket.set(person);
        
        // 从桶中获取对象
        Person newPerson = personBucket.get();
        System.out.println(newPerson.getName());
       
       
       
    }
    private static void list(RedissonClient redissonClient) {
        
        /*
            1. 调用redissonClient的getList方法,根据指定的key获取List类型的值
            2. 对于我们而言List类型的值就相当于内存中的一个List,所以之前怎么访问List,现在完全一样
            3. List中可以放基本数据类型及其包装类的值,也可以放对象
            4. 如果要修改Redis中List数据类型中的元素的值,还得把修改后的元素重新调用add方法
               添加到List才行
        */
        List<Person> list = redissonClient.getList("listKey");
        
        // ...

    }
    private static void set(RedissonClient redissonClient) {
        /*
            1. 调用redissonClient的getList方法,根据指定的key获取Set类型的值
            2. 对于我们而言List类型的值就相当于内存中的一个Set,所以之前怎么访问Set,现在完全一样
            3. Set中可以放基本数据类型及其包装类的值,也可以放对象
            4. 因为Set无序,所以仍然和之前一样,可以用迭代器或者stream流来访问
        */
        Set<String> set = redissonClient.getSet("setKey");
        set.add("setValue");

        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            System.out.println(next);
        }
    }
     private static void sortedSet(RedissonClient redissonClient) {
        /*
           1. 调用RedissonClient的getScoredSortedSet获取指定key对应的一个SortedSet
           2. Redisson用RScoredSortedSet对象表示一个SortedSet,该类所持有的泛型表示SortSet中元素对
              应的Java类型
           
           3. RScoredSortedSet中的每一个元素都绑定分数,所以添加的时候既要添加元素还要添加元素的score
           4. 可以获取元素的分数,排名...
           5. RScoredSortedSet中也可以放Java对象
           
        */
        RScoredSortedSet<String> sortedSet
                = redissonClient.getScoredSortedSet("sortedKey");
​
        sortedSet.add(1.0, "zs");
        sortedSet.add(2.0, "lisi");Double score = sortedSet.getScore("zs");
        System.out.println(score);
        Integer rank = sortedSet.rank("zs");
        System.out.println(rank);
    }
   private static void map(RedissonClient redissonClient) {

        /*
            1. 在redis中获取名为mapKey的名称的hash数据结构的值
            2. 获取到的是一个Map,就可以把它当做内存中的一个Map,所以之前怎么用Map现在还是一样
            3. Map中的key为String类型,Value可以是基本数据类型及其包装类的值,也可以是对象
            4. 如果要修改Redis中hash数据类型中的元素的值,还得把修改后的元素重新调用Map的put方法
               添加到Map中才行
        
        */ 
        Map<String, String> map = redissonClient.getMap("mapKey");

        //         "field"      "value"
        // 添加
        map.put("mapField", "mapValue");
        // 修改
        map.put("mapField", "v1");

       //获取
        String mapField = map.get("mapField");
        System.out.println(mapField);
       //删除
       map.remove("mapField");

    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/596573.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一个新细节,Go 1.17 将允许切片转换为数组指针!

在 Go 语言中&#xff0c;一个切片&#xff08;slice&#xff09;包含了对其支持数组的引用&#xff0c;无论这个数组是作为一个独立的变量存在于某个地方&#xff0c;还是仅仅是一个为支持分片而分配的匿名数组。 其切片基本结构都如下&#xff1a; // runtime/slice.go typ…

Sentinel流量防卫兵

1、分布式服务遇到的问题 服务可用性问题 服务可用性场景 服务雪崩效应 因服务提供者的不可用导致服务调用者的不可用,并将不可用逐渐放大的过程&#xff0c;就叫服务雪崩效应导致服务不可用的原因&#xff1a; 在服务提供者不可用的时候&#xff0c;会出现大量重试的情况&…

鸿蒙内核源码分析(原子操作篇) | 谁在为原子操作保驾护航

基本概念 在支持多任务的操作系统中&#xff0c;修改一块内存区域的数据需要“读取-修改-写入”三个步骤。然而同一内存区域的数据可能同时被多个任务访问&#xff0c;如果在修改数据的过程中被其他任务打断&#xff0c;就会造成该操作的执行结果无法预知。 使用开关中断的方…

CTF(Web)中关于执行读取文件命令的相关知识与绕过技巧

在我遇到的题目中&#xff0c;想要读取文件必然是要执行cat /flag这个命令&#xff0c;但是题目当然不会这么轻松。让你直接cat出来&#xff0c;必然会有各种各样的滤过条件&#xff0c;你要做的就是尝试各种方法在cat /flag的基础上进行各种操作构建出最终的payload。 下面我…

38-1 防火墙了解

一、防火墙的概念: 防火墙(Firewall),也称防护墙,是由Check Point创立者Gil Shwed于1993年发明并引入国际互联网(US5606668 [A]1993-12-15)。它是一种位于内部网络与外部网络之间的网络安全系统,是一项信息安全的防护系统,依照特定的规则,允许或是限制传输的数据通过。…

《QT实用小工具·五十八》模仿VSCode的可任意拖拽的Tab标签组

1、概述 源码放在文章末尾 该项目实现了模仿VSCode的可任意拖拽的Tab标签组&#xff0c;包含如下功能&#xff1a; 拖拽标签页至新窗口 拖拽标签页合并控件 无限嵌套的横纵分割布局&#xff08;类似Qt Creator的编辑框&#xff09; 获取当前使用的标签组、标签页 自动向上合并…

【CTF Reverse】XCTF GFSJ0490 simple-unpack Writeup(UPX壳+脱壳+反汇编)

simple-unpack 菜鸡拿到了一个被加壳的二进制文件 解法 拉进 exeinfope。 检测到是 UPX 打包的 ELF 文件。 NOT Win EXE - .o - ELF [ 64bit obj. Exe file - CPU : AMD x86-64 - OS/ABI: Linux/GNU ]Detected UPX! packer - http://upx.github.io -> try unpack with &…

Linux第三节--常见的指令介绍集合(持续更新中)

点赞关注不迷路&#xff01;&#xff0c;本节涉及初识Linux第三节&#xff0c;主要为常见的几条指令介绍。 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1f44d;&#x1f3fb; 收藏 ✨ 加关注&#x1f440; 期待与你共同进步! Linux下基本指令 1. man指令 Linu…

在uniapp里面使用 mp-html 并且开启 latex 功能

在uniapp里面使用 mp-html 并且开启 latex 功能 默认情况下 mp-html 是不会开启 latex 功能的, 如果需要开启 latex 功能是需要到代码操作拉取代码自行打包的。 这里说一下 mp-html 里面的 latex 功能是由 https://github.com/rojer95/katex-mini 提供的技术实现&#xff0c;…

科技园3d数据可视化展示

我们的园区安防3D可视化报警平台通过高精度三维建模技术&#xff0c;将管理对象场景以立体、直观的方式呈现&#xff0c;实现管理对象的全面可视化。同时&#xff0c;平台与各类业务系统深度对接&#xff0c;实现数据、告警、远程操作的整合展示和联动响应&#xff0c;构建中心…

Java基础教程 - 4 流程控制

更好的阅读体验&#xff1a;点这里 &#xff08; www.doubibiji.com &#xff09; 更好的阅读体验&#xff1a;点这里 &#xff08; www.doubibiji.com &#xff09; 更好的阅读体验&#xff1a;点这里 &#xff08; www.doubibiji.com &#xff09; 4 流程控制 4.1 分支结构…

CSS Web服务器、2D、动画和3D转换

Web服务器 我们自己写的网站只能自己访问浏览&#xff0c;但是如果想让其他人也浏览&#xff0c;可以将它放到服务器上。 什么是Web服务器 服务器(我们也会称之为主机)是提供计算服务的设备&#xff0c;它也是一台计算机。在网络环境下&#xff0c;根据服务器提供的服务类型不…

C++构造函数和析构函数的调用顺序

一般情况下&#xff0c;调用析构函数的次序正好与调用构造函数的次序相反&#xff0c;也就是最先被调用的构造函数&#xff0c;其对应的析构函数最后被调用&#xff0c;而最后被调用的构造函数&#xff0c;其对应的析构函数最先被调用。 当然对象的构造函数和析构函数调用时机和…

DRF的序列化【2】

【0】前提概要 【1】基于 View JsonResponse 编写的 5 个接口&#xff1a; 序列化自定义处理: 你需要自己编写序列化逻辑。处理 JSON 格式的 POST 请求数据: 从 request.body 中获取数据&#xff0c;并使用 json.loads() 解析成字典&#xff0c;然后创建相应的对象。request.…

JS基础:变量的详解

你好&#xff0c;我是云桃桃。 一个希望帮助更多朋友快速入门 WEB 前端的程序媛。 云桃桃&#xff0c;大专生&#xff0c;一枚程序媛&#xff0c;感谢关注。回复 “前端基础题”&#xff0c;可免费获得前端基础 100 题汇总&#xff0c;回复 “前端基础路线”&#xff0c;可获取…

基于51单片机NEC协议红外遥控发送接收proteus仿真设计

1.主要功能&#xff1a; 设计一个51单片机红外遥控发射接收proteus仿真设计 功能要求&#xff1a; 1、使用单片机模拟红外遥控器发射红外编码&#xff1b; 2、利用从机接收红外编码&#xff0c;并将编码以16进制显示到数码管上。 需注意仿真中51单片机芯片是兼容的&#x…

Web网页项目实战-----小兔鲜儿项目

本网站是一个电商网站&#xff0c;主要由Html、CSS、JS来完成&#xff0c;实现的功能主要是可以购买产品&#xff0c;展示产品&#xff0c;查看订单等功能&#xff0c;效果如下&#xff0c;如有需要项目代码的可以私信我&#xff0c;或者文章底下评论&#xff0c;我给分享原项目…

爬虫学习(2)破解百度翻译

代码 import requests import jsonif __name__ "__main__":url https://fanyi.baidu.com/sug#post请求参数处理&#xff08;同get请求一致&#xff09;headers {"User-Agent": Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, …

【C语言】第一个C程序:hello world

printf简介 printf是C语言提供的库函数&#xff0c;可以在屏幕上打印格式化数据。这里不作展开&#xff0c;只需要知道&#xff0c;如果要打印hello world&#xff0c;就把双引号引起来的"hello world"作为参数传给printf就行了。如果想要在打印后换行&#xff0c;要…

【Linux】冯·诺依曼体系结构

要想谈进程&#xff0c;我们就不能只谈进程&#xff0c;我们如果想搞清楚什么是进程&#xff0c;就要从操作系统讲起。我们现在的不管是Linux或是Windows或是安卓等操作系统&#xff0c;它们都有一个相同点&#xff0c;那就是遵循冯诺依曼体系结构&#xff0c;我们看一下冯诺依…
最新文章