Redis进阶学习笔记

阅读Redis.conf配置文件

# 61, 绑定的 IP , 一般注释掉该命令,这个吗,命令表示仅接受本机的(IP为本机)客户端连接,
bind 127.0.0.1 # 80, yes: 保护模式 , 默认关闭, 允许外部客户端连接redis,no: 只能本机连接
protected-mode no# 84, 端口号
port 6379####### 整体配置 GENERAL ########## 129, yes: 开启守护进程模式,重启机器, redis自启动,no: 机器重启需要手动启动redis
daemonize no# 150, pid文件生成目录
pidfile /var/run/redis_6379.pid# 158, 日志级别,
# Redis 总共支持四个级别:debug、verbose、notice、warning
#  - debug:会打印生成大量信息,适用于开发/测试阶段
#  - verbose:包含很多不太有用的信息,但是不像debug级别那么混乱
#  - notice:适度冗长,适用于生产环境
#  - warning:仅记录非常重要、关键的警告消息
loglevel notice# 163 , 打印日志目录
logfile ""# 177, 16哥数据库
databases 16########  快照  SNAPSHOTTING  ############ 快照 , 持久化操作,保存 redis数据库中的一个状态,用于恢复数据库,将redis持久化到 .rdb .aof文件中
#  - 900s,至少有 1 个key 发生了变化,才会持久化
#  - 300,至少有 10 个key 发生了变化,才会持久化
#  - 60s,至少有 10000 个key 发生了变化,才会持久化
save 900 1
save 300 10
save 60 10000# 219 , 持久化错误之后是否要工作
stop-writes-on-bgsave-error yes# 225 , 是否压缩 rdb 文件
rdbcompression yes# 234, 保存rdb文件是否要进行错误检查校验
rdbchecksum yes# 236,rdb 文件的文件名
dbfilename dump.rdb# 247, rdb 文件保存路径
dir ./################## 安全设置 SECURITY #################### 480 ,设置密码 , 也可使用命令配置
requirepass 123456##### 命令配置密码> config set requirepass 123> config get requirepass> auth 123
##### end################ LIMITS #############
# 512 , redis的最大链接数
maxclients 10000# 537, redis配置的最大内存
maxmemory <bytes># 内存达到上限之后的处理方法
# - volatile lru    ->  设置了过期时间的key进行lru移除
# - allkeys lru     ->  删除所有
# - volatile random ->   删除即将过期的key
# - allkeys random  ->   随机删除
# - volatile ttl    ->   删除即将过期的
# - noeviction      ->   永远不过期,直接报错
maxmemory-policy noeviction############# AOF持久化 ###############
# 593,yes开启AOF持久化,默认是不开启的,默认使用RDB持久化,大部分情况下RDB完全够用
appendonly no# 597 ,aof持计划文件名
appendfilename "appendonly.aof"# 623 , 每次修改都会synch 消耗性能
#  - always , 每次修改都进行 aof持久化
#  - everysec , 每秒进行aof持久化
#  - no , 从不
appendfsync everysec

Redis持久化

Redis是内存数据库,断电即失去,只要是内存数据库就一定会有持久化操作

RDB(Redis DataBase)

在指定的时间 间隔内将内存中的数据集快照写入到磁盘中,Snapshot快照,恢复时将快照文件直接读到内存中

RDB流程
  • 单独创建一个子进程,fork分支
  • 将内存内容写入临时RDB文件
  • 再用临时文件替换上次持久化完成的文件

​ 整个过程主进程不进行任何io操作,保证了性能,如果进行大规模数据恢复,RDBAOP都可以进行数据恢复,AOF数据恢复完整性不敏感,RDB更加高效,缺点时最后一次持久化后的数据可能丢失,默认使用的就是RDB,一般情况不需要修改这个配置

  • RDB保存的文件是dump.rdb
  • AOF保存的文件是appendonly.aof
dump.rdb文件

触发机制
  • save规则触发
  • 执行flushall命令
  • 关闭redis
如何恢复备份文件

​ 只要将rdb文件放在redis规定的目录,redis启动时会自动检查dump.rdb文件恢复数据,在生产环境中最好对dump.rdb文件进行备份

RDB优缺点

优点:

  • 父进程正常处理用户请求,fork分支一个子进程进行备份
  • 适合大规模的数据恢复,如果服务器宕机了,只要不删除RDB文件,重启以后还可以恢复数据**(最后一次的数据无法恢复,因为还没有生成新的rdb文件,就宕机了)**

缺点:

  • 需要一定的时间间隔,可以自行修改设置
  • 如果redis意外宕机,最后一次的修改数据会丢失
  • fork进程的时候,会占用一定的内存空间

AOF(Append Only File)

  • 将所执行的所有命令都记录下来,处读操作以外,恢复时重新执行一次,如果是大数据就需要写很久
  • aof默认是文件无限追加,大小会不断扩张
  • 在主从复制中,rdb是备用的,在从机上使用,aof一般不使用

AOF的本质就是保存 所有执行了命令

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gtnk4kn9-1666273048108)(images/image-20211020092943332.png)]

AOF流程
  • fork分支出子进程
  • 根据内存中的数据子进程创建临时aof文件
  • 父进程执行的命令存放在缓存中,并且写入原aof文件
  • 子进程完成新aof文件通知父进程
  • 父进程将缓存中的命令写入临时文件
  • 父进程用临时文件替换旧aof文件并重命名
  • 后面的命令都追加到新的aof文件中
开启AOF
appendonly no
#默认关闭appendonly 手动设置yes开启appendfilename "appendonly.aof"
#默认名字# appendfsync always
appendfsync everysec
# appendfsync no
#每次都进行修改
#每秒钟都进行修改 ,
#不进行修改no-appendfsync-on-rewrite no
#是否进行重写auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
#percentage重写百分比
#重写时文件最小的体积#一般保持默认,一般只需要开启

一般采用 appendfsync everysec 每秒钟触发一次,这样就算是宕机,也最多丢失1秒钟的数据。

测试开启aof
root@root:~# redis-cli -a 123456
127.0.0.1:6379> set name san
OK
127.0.0.1:6379> get name
"san"
127.0.0.1:6379> exit
root@root:~# cd /usr/local/redis/redis-3.2.10/
root@root:/usr/local/redis/redis-3.2.10# ls
00-RELEASENOTES  COPYING   Makefile    runtest           src
appendonly.aof   deps      MANIFESTO   runtest-cluster   tests
BUGS             dump.rdb  README.md   runtest-sentinel  utils
CONTRIBUTING     INSTALL   redis.conf  sentinel.conf

redis目录生成了appendonly.aof文件

我们看到 AOF文件中存储的是我们的命令

破坏AOF文件以及修复aof文件

appendonly.aof文件中加入一串符号

重启Redis,发现redis重启失败
使用redis-check-rdb修护aof文件
root@root:/usr/local/redis/redis-3.2.10# vim appendonly.aof
root@root:/usr/local/redis/redis-3.2.10# redis-check-aof --fix /usr/local/redis/redis-3.2.10/appendonly.aof
0x              37: Expected prefix 'b', got: '*'
AOF analyzed: size=90, ok_up_to=55, diff=35
This will shrink the AOF from 90 bytes, with 35 bytes, to 55 bytes
Continue? [y/N]: y
Successfully truncated AOF
root@root:/usr/local/redis/redis-3.2.10# cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
set
$4
name
$3
san
root@root:/usr/local/redis/redis-3.2.10#

修复成功,删除了我添加的乱码

优缺点

优点:

  • 可设置文件修改每次都同步备份,文件完整性更好,但是消耗性能
  • 设置每秒同步一次可能会丢失一秒的数据
  • 从不同步效率最高

缺点

  • 对于数据文件,aof远远大于rdb,修复速度也比rdb
  • aofio操作,所以默认是aof
  • aof文件会无限扩大

所有我们一般不使用aof,而是使用rdb用作备份

Redis主从复制

一个Master有多个slave,将一台redis服务器数据,复制到其他的redis服务器,前者称为主节点(masterleader),后者称为从节点(slave、follower)数据是单向的,只能从主节点到从节点,Master以写为主,Slave以读为主

主从复制的特点

主从复制的特点

  • 数据是单向的,只能从主节点到从节点
  • Master以写为主,Slave以读为主
  • 主节点和从节点的数据都是一样的,主节点数据发生变化是,会同步所有从节点的数据。
  • 一个Master可以有多少Slave或没有从节点,一个从节点只能有一个主节点

默认情况下(非主从结构时),每台redis服务器都是主节点,一个Master可以有多少Slave或没有从节点,一个从节点只能有一个主节点

主从复制作用包括:

  • 数据冗余,实现了数据的热备份,是持久化之外的一种数据冗余方式
  • 故障恢复,主节点出现问题,从节点可以提供服务,实现快速的故障恢复,实际上是一种服务的冗余
  • 负载均衡,在主从复制的基础上,配合读写分离,主节点提供写服务,从节点提供读服务,写redis数据时连接主节点,读redis数据连接从节点,分担服务器负载,尤其在写少读多的场景下通过,多个从节点分担负载,可以提高redis性能
  • 高可用(集群)基石,哨兵、集群,能够实施的基础,主从复制时高可用的基础

不能只使用一台redis的原因:

  • 从结构上讲,单个redis服务器会发生单点故障,一台服务器需要处理所有请求,压力大
  • 从容量上讲,单个redis服务器内存容量有限,并且不能完全使用全部的内存,单台redis的最大内存不应该超过20g压力过大

通常的电商网站都是一次上传吗,无数次浏览,读多写少 ,主从复制,读写分离,80%的情况都在进行读操作,起码一主二从

搭建Redis主从复制伪集群

cp三份redis.con文件到新的目录

cp三份redis.con文件到新的目录以80、81、81重命名

root@iZ2ze3e3cxev6ehgdt3qpdZ:~/redis# ls
redis80.conf  redis81.conf  redis82.conf  redis.conf
root@iZ2ze3e3cxev6ehgdt3qpdZ:~/redis#
修改三个配置文件的内容
# 1. 修改端口 6380、6381、6382
port 6380# 2. 修改 pid 的文件名
pidfile /var/run/redis_6381.pid# 3. 修改日志文件6380、6381、63812
logfile "6381.log"# 4. 修改rdb文件名80、81、82
dbfilename dump81.rdb
分别启动三个redis
root@root:~/redis# redis-server redis80.conf
root@root:~/redis# redis-server redis81.conf
root@root:~/redis# redis-server redis82.conf# 启动服务 redis-cli -p 6380 -a 123456
root@root:~/redis#

6380

6381

6382

建立主从结构

主机master6380

从机slave63816382

slaveof 127.0.0.1 6379  # 设置 6380 为主机
info replication  # 查看 配置信息

从机设置主机,在6381、6382分别设置6380为主机

127.0.0.1:6381> slaveof 127.0.0.1 6379  # 设置 6380 为主机
OK
127.0.0.1:6381> info replication  # 查看 配置信息
# Replication
role:slave  # 表示自己为从机
master_host:127.0.0.1
master_port:6380
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:1634715585
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6381>
127.0.0.1:6382> slaveof 127.0.0.1 6380  # 设置 6380 为主机
OK
127.0.0.1:6382> info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:6380
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:1634715709
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
127.0.0.1:6382>
查看的主机6380的配置信息
127.0.0.1:6380>  info replication
# Replication
role:master
connected_slaves:2
slave0:ip=127.0.0.1,port=6381,state=online,offset=43,lag=1
slave1:ip=127.0.0.1,port=6382,state=online,offset=43,lag=0
master_repl_offset:43
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:42
127.0.0.1:6380>

主从复制搭建成功

注意:

如果redis设置了密码,主从结构会失败,会出现主机找不到从机的问题

解决方法:

​ 从机在添加主机时,加上密码参数

主节用于写数据,从节点用于读数据

127.0.0.1:6381> set name san
(error) READONLY You can't write against a read only slave.
127.0.0.1:6381>

如果我们对从节点写数据,就会失败,只有主节点才可以写数据

######## master
127.0.0.1:6380> set name san
OK
127.0.0.1:6380>######## slave
127.0.0.1:6381> get name
"san"
127.0.0.1:6381>

无哨兵的主从结构存在的问题

=====================================>

由此可见,如果主机一直宕机,从机一直都会是从机,将会导致系统不可用。如果主机恢复,主从配置没有写入到redis.conf文件中,将读取不到主机设置的值。

<=====================================

主从复制的原理

  • slave启动成功连接到master后会发送一个sync同步命令

  • master接到命令,启动后台的存盘进程,同时收集所接收到的用于修改数据集命令,后台执行完毕之后,master将传送整个数据文件到slave,并完成一次同步,成为增量复制

  • 只要重新连接master,**一次完全同步(全量复制)**将被自动执行,数据一定能在从机中看到

全量复制和增量复制
  • 全量复制,就是将主机的所有数据文件,全部同步。一般用在连接成功后,主机的一系列操作。
  • 增量复制,就是将同步对主机自己没有的数据。一般用在连接成功时,需要同步主机的所有数据。

主从复制

的两种结构

  • 星型结构,所有从节点都直接连接在主节点上。

  • 链式结构,只有一个从节点直接到主节点,其他节点间接连接

    # 实现方式
    # 在 salve1:6380 设置主节点
    slaveof 127.0.0.1 3679
    # 在 salve2:6381 认 salve1 问主节点slaveof 127.0.0.1 3680
    

    这两种方法都一样,主机宕机,从节点都无法变成主节点

Master宕机解决方法

  • 手动让从机变为主机 , 需要人工手动设置十分不方便

    slaveof on one
    # 让自己变为主机
    
  • 使用哨兵根据投票自动选择从机变为主机 , 哨兵模式更加适用。

带哨兵模式的主从复制

​ 哨兵模式是一种特殊模式,哨兵是一个独立的进程,作为进程独立运行,原理是哨兵通过发送命令,等待redis服务器响应,从而判断服务器是否存货

单机哨兵

​ 哨兵向服务器发送信息,如果服务器没有一定时间内响应,就认为该服务器宕机。哨兵检测到master服务器宕机后,会自动将slave切换成master,通过发布订阅模式通知其他的从服务器,修改配置文件,让他们切换主机

单机哨兵宕机也会存在一定的风险,创建多个哨兵构建集群才是正解!

哨兵集群模式
  1. master宕机,sentinel检测到这个结果系统并不会马上进行failover(故障切换、失效备援)这个现象称为主观下线, 也就是不会马上切换主机。
  2. 等待其他哨兵也检测到主机不可用,sentinel之间会发起一次投票,(投票的结果由随机一个sentinel发起,进行failover操作)得到票数最多的从机就就切换成主机。
  3. 切换成主机后,通过发布订阅模式,让各个哨兵把自己监控的服务器实现切换主机,这个过程称为客观下线

单哨兵模式实现

创建哨兵配置文件 sentinel.conf
# sentinel.conf
sentinel monitor mymaster 127.0.0.1 6380 1
# sentinel monitor   mymaster(主机的名称,随便写)  主机IP  端口
# 1 表示: (法定人数)至少需要 1 个哨兵同意的情况下,才可以让从机变为主机

有的redis目录下就有sentinel.conf文件只需要对其修改即可。

启动哨兵模式
redis-sentinel sentinel.con

  • 启动sentinel成功之后看到,监控了6381、6382、6380的健康状态。
  • 端口为26379
  • 如果哨兵检测到master宕机,则会打印检测信息
测试master宕机

稍微等待一会,sentinel打出信息, 6380宕机,6382上位

连接6382查看主从信息,发现6382变为主机

如果6380恢复,那么6380是否还是主机呢?

很明显,6380就算恢复,也只能是从机,无法恢复成主机。

多哨兵集群配置

多哨兵集群的配置和单哨兵是一样的
  • 复制三份sentinel1.confsentinel2.confsentinel3.conf即可

  • 修改sentinel.conf中的port段口号即可,默认端口号26379,三个不一样的端口号。

  • 监视主机的配置写法一样

    sentinel monitor mymaster 127.0.0.1 6379 2
    

哨兵模式优缺点

优点

  • 基于集群,基于主从复制,所有的主从配置的优点,它全有
  • 主从可以切换,故障可以切换,系统的可用性提高
  • 哨兵模式就是主从模式的升级,手动到自动,更加健壮

缺点

  • redis不好在线扩容,集群容量一旦达到上限,在线扩容就十分麻烦
  • 哨兵模式需要很多配置
    • 多哨兵,多端口配置复杂,一般由运维来配置

Redis缓存穿透、击穿、雪崩

服务三高

  • 高并发
  • 高可用
  • 高性能

Redis缓存

redis缓存的使用极大的提升了应用程序的性能和效率,特别是数据查询方面,但是也带来了许多问题,如数据一致性问题,对一致性要求高的不推荐适用缓存。

缓存穿透

​ 用户查询一个数据,redis数据库中没有,也就是缓存没命中,于是向持久层数据库查询,发现也没有,于是查询失败,用户很多的时候,缓存都没有命中,都请求持久层数据库,给持久层数据库造成巨大压力,称为缓存穿透。(由于缓存没有命中,大量的请求冲击数据库,导致缓存穿透)

解决方法
  • 布隆过滤器,在直达持久层的路径上加上过滤器
  • 缓存空对象,缓存中专门增加一个为空的请求

布隆过滤器

布隆过滤器是一种数据结构,对所有可能的查询参数以hash形式存储,在控制层进行校验,不符合则丢弃,从而避免了对底层存储系统查询压力

缓存空对象

​ 当持久化层不命中后,将返回的空对象存储起来,同时设置一个过期时间,之后再访问这个数据就从缓存中获取,保护持久层数据源

设置空缓存的问题
  • 存储空的key也需要空间
  • 对空值设置了过期时间,还会存在缓存层和存储层的数据有一段时间窗口不一致,对于需要保持一致性的业务会有影响

缓存击穿

例子微博服务器热搜,巨大访问量访问同一个key

​ 一个key非常热点,不停扛着大并发,集中对一个点进行访问,当个key失效的瞬间,持续大并发导致穿破缓存,直接请求数据库

​ 某个key在过期的瞬间,大量的访问会同时访问数据库来查询最新的数据,并且回写缓存,导致数据库瞬间压力过大

======================================

一句话说,就是某个热点key承受不住高压(或者突然过期),导致大量请求直接访问数据库,导致缓存穿透。

======================================

解决方案
  • 设置热点数据不过期,但是一直缓存会导致浪费空间
  • 加分布式锁:使用分布式锁,保证对于每个key同时只有一个线程查询后端服务,其他线程没有获得分布式锁的权限,只需要等待即可,这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大

缓存雪崩

在某一个时间段,缓存集中过期失效,redis宕机

产生雪崩的原因之一,设置缓存的存活时间较短,大并发访问时刚好都过期,直接访问了数据库,对数据库而言,会产生周期性压力波峰**,暴增时数据库可能会宕机**

==========================================

一句话:就是突然大量的缓存失效,大量数据访问数据库,数据库承受不住压力宕机了,导致其他所有服务不可用,就像雪崩一样。

==========================================

解决方法
  • 异地多活、增加redis集群服务器的数量
  • 加分布式锁、缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量,对某个key只允许一个线程查询数据和写缓存,其他线程等待
  • 限流降级、控制访问流量,对高并发的流量进行限制,并使用降级策略。
  • 数据预热,正式部署之前,把可能的数据提前访问一遍,可能大量访问的数据就会加载到缓存中,加载不同的key,设置不同的过期时间,让缓存时间尽量均匀

Redis 进阶学习笔记相关推荐

  1. opencv进阶学习笔记3:像素运算和图像亮度对比度调节

    基础版传送门: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版目录: python+opencv进阶版学习笔记目录(适合有一定基础) 像素运算 要求两张图大小,以及格式(np ...

  2. JavaSE进阶学习笔记-目录汇总(待完成)

    声明:此博客来自于黑马程序员学习笔记,并非商用,仅仅是为了博主个人日后学习复习用,如有冒犯,请联系qq208820388立即删除博文,最后,来跟我一起喊黑马牛逼黑马牛逼黑马牛逼 JavaSE进阶学习笔 ...

  3. UnrealEngine蓝图进阶学习笔记(六):按波次生成敌人

    UnrealEngine蓝图进阶学习笔记(六):按波次生成敌人 2020.04.03 一.创建敌人生成点及相关变量 1.部署生成点 左部面板搜索TargetPoint至场景(2250,0,0),ctr ...

  4. Redis进阶学习08--多级缓存

    Redis进阶学习08--多级缓存 什么是多级缓存 JVM进程缓存 环境准备 docker安装mysql docker安装nginx 反向代理 初识Caffeine 实现JVM进程缓存 需求 实现 L ...

  5. redis安全学习笔记

    redis安全学习笔记 [toc] 文章部分内容首发于xray社区公众号 基础 https://www.runoob.com/redis/redis-tutorial.html 环境 : ubuntu ...

  6. 尚硅谷Redis 7学习笔记

    尚硅谷Redis 7学习笔记 视频链接 新手入门篇 1.安装及数据类型 2.持久化 3.Redis 7 事务.管道.发布订阅.主从.哨兵.集群 4.springboot整合redis 高级篇(更新中- ...

  7. opencv进阶学习笔记14:分水岭算法 实现图像分割

    基础版学习笔记目录: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 分水岭算法原理 分水岭算法 ...

  8. opencv进阶学习笔记13:图像形态学操作大全(膨胀,腐蚀,开闭,黑帽,顶帽,梯度)python版

    基础版学习笔记: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 基础版形态学: opencv学 ...

  9. opencv进阶学习笔记12:轮廓发现和对象测量

    基础版笔记目录: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 轮廓发现 1轮廓发现介绍 基础 ...

最新文章

  1. spring的依赖注入方式详解
  2. boost::proto::display_expr相关的测试程序
  3. 数据库-聚合函数-max函数
  4. 设计模式 日志系统设计_模式:我们设计系统的故事
  5. wordcloud python3.6能用吗_Python3.6环境下安装wordcloud模块遇到的问题及解决办法
  6. Github Pages建立个人博客
  7. python字符串赋值与java区别_java和python细节总结和java中string 的+操作
  8. validation 参数校验和统一异常处理
  9. 计算机视觉领域常见期刊和会议,计算机视觉领域常见期刊和会议
  10. 判断二叉树是否平衡二叉树
  11. easyUI跨Tab操作datagrid
  12. 做个简单的Java学生考勤系统06--签到功能完善
  13. bootice添加黑苹果引导_Clover(四叶草)引导多系统(Linux亦可),黑苹果引导教程
  14. xshell 使用教程
  15. ThinkPad E431 Bluetooth驱动
  16. linux下的键盘检测
  17. “2018 Unreal Open Day 虚幻引擎技术开放日”活动开启预售
  18. java以太网通讯西门子plc300_3套300PLC之间的以太网通讯
  19. Linux环境下搭建Apache服务器(完整版)
  20. 计算机房防水,机房如何做到防水?

热门文章

  1. Python3 教你如何写一个登录器
  2. div铺满全屏的三种方式
  3. linux 音频处理工具,Linux 上的最佳音频编辑工具推荐 | Linux 中国
  4. java 自动生成抽象的图片
  5. [转] Unity实战之见缝插针
  6. 关于Proteus仿真闪退及Proteus上电瞬间电容初始电压设定问题解决办法总结
  7. 动车的座位排序[转]
  8. IBATIS入门小例子
  9. 考研机试准备--《王道论坛机试指南》学习笔记
  10. Python批量ipynb文件转(另存为)pdf