概述
- 广泛使用的内存缓存
- 使用多路IO进行事件驱动的单线程处理所有事件的操作
- 启动 Redis => docker => docker redis => 默认端口映射 6379 =>
docker run --name first-redis -p 6379:6379 -d redis
操作系统基本原理
- CPU 是时钟驱动的,基本执行单位是指令
- 指令来自程序的代码段
- CPU 读取程序的代码段,挨个执行指令
- 可以从内存和寄存器交换数据
- 可以执行计算
- 可以跳转
- 某一个时刻只有一个进程或线程占有 CPU,执行指令
当上下文切换发生时
CPU 需要:
- 保存现场 => 正在执行的任务的所有寄存器
- 恢复现场 => 即将被执行的任务的所有寄存器
上下文切换有多慢: 切换上下文需要数千个时钟周期
Redis 为什么这么快
- 完全基于内存 => CPU(10^-9 s == 1ns) 比内存快3个数量级,内存比硬盘快3个数量级 => CPU 是时钟周期驱动的,CPU的速度比内存快大约3个数量级
- 优秀的数据结构设计
- 单一线程,避免上下文切换的开销和避免锁的开销
- 事件驱动,非阻塞
- IO 多路复用机制
IO 多路复用机制
- 如何从操作系统的 IO 中读写数据? => recv(receive)/send 系统调用(recv/send 默认阻塞) => 阻塞了多个线程 => 线程昂贵 + 上下文切换 => IO 多路复用:一个线程可以同时服务海量的 Socket 连接
IO 模型
- Blocking IO => recv 阻塞至有数据返回 => FileInputStream.read() => Reads a byte of data from this input stream. This method blocks if no input is yet available.
- Non-blocking IO => 如果无数据,recv 立即返回,给出一个状态码
多路 IO
- 同时监控多个 Socket
- select | poll
- 监控多个 file descriptor(FD 文件描述符)
- 功能几乎相同,共用代码
- 当返回时,需要轮询 PF 列表检查是否有事件发生
- epoll => 当返回时,只要有事件发生的 FD 会被返回 => Redis 使用 epoll
数据结构
Structure Type | What is contained |
---|---|
String | String, Integers, or floating-point values |
List | Linked list of strings |
Set | Unordered collection of unique strings |
Hash | Unordered hash table of keys to values(Java HashMap, key-value must be a string) |
ZSet(sorted set) | Ordered mapping of string members to floating-point scores, ordered by score(有序的集合, TreeSet) |
Spring Boot Redis
@Bean
- 创建 RedisTemplate
-
@Autowired
RedisTemplate
Redis 存在最大的意义在于在多个机器分布式集群中共享数据
Java Object 序列化 => 字节流 => java.io.Serializable
在 Spring Boot 中使用 Redis
- docker 启动 Redis 服务
- 配置 Redis Spring Boot starter
- 在 Spring 中配置 Redis
spring.redis.host=localhost // 本机 spring.redis.port=6379
- 配置 Redis Template
注意@Configuration public class ApplicationConfig { @Bean RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(redisConnectionFactory); return redisTemplate; } }
- 在使用的地方注入即可
知识点
- 阻塞 vs 死循环
- 阻塞 => 不占用 CPU
- 死循环 => 占用 CPU 100%
- Java 中一个线程大约占用 1M - 4M 的内存 => 一个 JVM 中最多就开几千个线程
- // TODO: bitmap
网友评论