notes
  • notes
  • codes
    • 安卓脚本
    • redis入门指南
    • js 原型链
    • 如何发布npm
    • go字符串
    • redis
    • this指向
    • go1.13
    • go by example
    • hook
    • go指南 - 官网
    • git基本操作
  • vim
  • training
    • 9月19日 ubc讲座
    • zby
      • DAY 3 :硬拉 | ZBY
      • DAY 2:卧推 | ZBY
      • DAY 1:深蹲 | ZBY
      • DAY 4 :计划 | ZBY
    • 汉唐
    • 周旋康复课
  • book notes
    • 思考致富
    • 邓普顿教你逆向投资
    • 阮琦
    • 魔鬼经济学
    • 网络是怎样连接的
    • 好奇心
    • 魔鬼约会学5.0
    • 股票作手回忆录
    • 漫步华尔街
    • 码农翻身
    • 十分钟速成课 - 哲学
    • 魔鬼答疑
    • 大话数据结构
    • 魔鬼约会学笔记
    • 算法图解
  • 狼人杀
  • 图书馆
  • typora
  • imovie
Powered by GitBook
On this page
  • 第一章 简介
  • 多数据库
  • 存储结构
  • key命名
  • 第二章 数据类型
  • 字符串
  • hash
  • 列表
  • 集合
  • 有序集合
  • 第四章 进阶
  • 4.1 事务multi/exec
  • 4.2 过期时间expire
  • 4.3 排序sort
  • 4.4 消息通知
  • 4.5 管道pipelining
  • 4.6 空间优化
  • 第六章 脚本
  • 第七章 持久化
  • RDB
  • AOF
  • 第八章 集群
  • 8.1复制
  • 8.2哨兵
  • 8.3 集群
  • 第九章 管理
  • 9.1 安全
  • 9.3第三方管理工具

Was this helpful?

  1. codes

redis入门指南

第一章 简介

字典形式存储,数据结构无法嵌套。更贴近程序。

数据存在内存中,需要持久化,异步写入硬盘。常作为缓存、队列。

所有操作都是原子的。

可以设置key的生存时间、最大内存、阻塞式读取、发布/订阅模式

多数据库

select命令更换数据库,数字编码,无法命名。默认链接0号。

不支持访问密码,全访问/不访问

数据库之间不完全隔离,更像是命名空间。最好放相关的数据,如生产/测试

不同应用应该用不同的redis实例来存储。

存储结构

不同数据结构,有不同命令前缀,不能混着用

换言之不同前缀的set,也就声明了不同数据结构

  • 字符串string

  • 散列hash - H

  • 列表list - L

  • 集合set - S

  • 有序集合zset - Z

key命名

对象类型:对象ID:对象属性,多个单词用.分隔

  • keys * 遍历存的所有的key

第二章 数据类型

字符串

最多512m

  • set key value

    get key

  • incr key 递增

  • exists key

  • del key [key...]

hash

key是字典名,里面有字段field和字段值value

字段值只能是字符串。

  • hset key field value 插入/更新

    hget key field

  • hmset key field value [key value…] 多存多取

    hmget ...

  • hgetall key

  • hexists key field

  • hsetnx key field value 不存在则赋值

  • hincrby key field increment 增加数字

  • hdel key field [field ...]

  • hlen key 数量

列表

可以向列表两端添加元素,或获取某个片段。

内部用双向链表,所以越接近两端,访问速度越快,中间或索引访问很慢。

更适合新鲜事、排名、记录日志。

  • lpush key value [value...] rpush key value [value...]

  • lpop key

    rpop key

  • llen key

  • lrange key start stop 支持负索引,最右是-1,lrange key 0 -1就是获取全部

  • lrem key count value 删除前count个值为value的元素,返回实际删除个数

    count>0,从左;<0从右,=0,删除所有

  • lindex key index 获取索引值

  • ltrim key start end 只保留选中片段

  • linsert key before/after pivot value 从左往右在第一个pivot前/后插入value

  • rpoplpush source destination source列表右边弹出,destination左边插入 可以做一个执行堆栈

集合

每个元素不同,且没有顺序。可以并、交、差。

底层用key为空的hash。

适合文章标签之类的

  • sadd key member [member…] 已存在会忽略,返回增加了多少元素

    srem key member [member...]

  • smembers key 获取所有元素

    scard key 元素个数

  • sismember key member 判断是否在集合中

  • spop key 随机弹出一个元素

运算

  • sdiff key [key...]

    差,A-B

  • sinter key [key...]

    交,A∩B

  • sunion key [key...]

    并,A∪B

有序集合

集合每个元素都关联一个分数,不同元素可以分数相同。

底层是hash表+跳跃表,读取中间位置也很快

跳跃表:每个节点随机有多少个节点,来链接后面

可以方便的调整某个元素位置,但比列表更占内存。

  • zadd key score member [score member ...]

  • zscore key member 获得元素分数

  • zrange key start stop [withscores] 获得排名在某范围为元素,含两端

    有withscores会带上分数

  • zincrby key increment member 增加某个元素分数

  • zcard key 获得集合元素数量

    zcount key min max 指定分数范围内元素个数

第四章 进阶

4.1 事务multi/exec

一组命令的集合,要么都执行,要么不执行。

而且保证执行过程中,无法被其他命令插入

但执行失败了无法回滚,得手动收拾烂摊子。

multi
...  // 命令
exec

如果中间命令加入成功,会返回queued

错误

  • 语法错误

    返回错误,然后后面命令就不执行了

  • 运行错误

    其他命令照样执行(前后)

锁:watch

就是监听一个值,如果被修改了,之后的事物就不会再进行了。

然后要手动回滚+重新运行函数

可以在事务一半手动unwatch放开

4.2 过期时间expire

  • expire key seconds

精确到秒

pexpire key ms,精确到毫秒

  • ttl key

    查询还有多久会被删除 被删了之后返回-2,如果没有设置过期时间,返回-1

  • persist key 取消过期时间

最大可用内存

maxmemory

超过了会lru,最近最少使用,来删掉不用的

访问频率限制

列表,记录用户最近10次访问时间。如果最早的访问在1分钟内,就报错。

4.3 排序sort

有序集合适合场景,是大数据排序。

sort key

集合、列表、有序集合

  • sort key alpha,根据字母排序

没有的话就转成双精度浮点数来排序

  • sort key desc 降序

  • sort key by field->value

field里面必须有*,会根据*的值来排序。

sort tag by post:*->time

在其他地方,或者没有*,都不能排序

  • … get field->value

排序后返回field里面的*,对应的内容

sort tag by post:*->time get post:*->title

id是#

  • … store ${value} 来把结果存到某个变量里

性能优化

复杂度是O(n+mlog(m)),m是要返回元素个数,n是要排序的元素个数

  • 待排序要少

  • 取出来的要少

  • 数据量大,用store缓存结果

4.4 消息通知

任务队列

用独立线程来放队列,队列两边是生产者和消费者

  • 生产者producer,给任务的人。把任务放进任务队列

  • 消费者consumer,做任务的人。从队列读任务并执行

可以有多个消费者

  • brpop queue 0,没有元素就会一直阻塞,就不用空数组还拼命读了

    0是超时时间,没新的元素,就会永远堵塞

优先级队列

blpop key [key…] timeout

同时检测多个键,所有键都没有元素就堵塞。

不然从左到右读取。因此优先的队列可以放在左边

发布/订阅

发布:publish channel message

订阅:subscribe channel [channel...]

订阅者无法获得订阅之前的消息

4.5 管道pipelining

为了减少网络传输,最好一口气发多条命令,然后一次性把结果返回

4.6 空间优化

数量少的时候,用效率更低,但占用空间更少的数据结构。到了一定数量再换回原本数据结构。

转换过程不可逆,数量减少了依然保持原本的数据结构。

字符串

  • 小于64位有符号整数,用long类型。

    能节约一半空间

sdshdr类型,包括了字符串长度、buf剩余空间、内容

  • redisObject

启动时会预先建立10000个数字,作为共享对象。就10000内只用存指针

即存小数字不用额外内存。

  • 键值内容不超过39字节,用redis_encoding-embstr编码

    超过了用redis_encoding_raw编码

散列类型

  • key/value/总数,少于hash-max-ziplist-entires

用redis_encoding_ziplist存

  • 有一个超过了,就用redis_encoding_ht

redis_encoding_ziplist

  • 存前一个元素大小,方便倒序找

  • 编码类型、元素大小、是否数字类型(更加省空间)

  • 实际内容

实际存,就是一个列表,field、value并列。要找的话从头一个个找

列表类型

  • redis_encoding_linkedlist,双向链表

  • redis_encoding_ziplist

  • redis_encoding_quicklist

    将长列表变成若干链表组织的ziplist

集合类型

小于set-max-intset-entires用redis_encoding_intset,多了用redis_encoding_ht

  • redis_encoding_intset

有序存储,二分查找。

有序集合

小了用ziplist,不然是skiplist

  • redis_encoding_skiplist

用hash和跳表来存储。

hash表,存元素值和元素分数

跳表,存分数到元素值的映射

第六章 脚本

可以用Lua语言,写脚本,然后传到redis中执行

把逻辑用脚本实现,程序就更容易升级和扩展

第七章 持久化

  • 缓存穿透:查一个数据库里面不存在的东西,找不到,于是就不断请求redis,再不断请求数据库,导致数据库宕机

可以返回一个空,就每次查询,redis直接返回查不到

  • 缓存雪崩:很多缓存同一时间失效,然后redis同时请求数据库一堆内容,导致数据库宕机

每个缓存失效时间要设置的不同,不能同时失效

redis支持两种持久化:

  • RDB:根据规则,定时把内存数据存在硬盘上

  • AOF:记录执行了哪些命令

一般两者一起用

RDB

根据规则生成快照(snapshotting),记录修改了哪些地方

异常退出,就只会丢失最后一次快照后更改的内容。

规则

  • 直接执行save,同步存

    bgsave,异步存

  • 配置文件中规定更新时间

save 900 1,900s内有一次以上改动,就更新。

多条规则是或关系

  • flushall,刷新。清除数据库所有数据,执行快照

  • 主从模式,复制时快照

快照原理

  1. fork()复制当前进程副本

  2. 子进程开始把内存中的数据写入硬盘中的临时文件

    这是经过压缩的数据,占用空间会小于内存大小

  3. 写完所有数据,才把临时文件替换旧dump.rdb文件。

    换言之,任何时刻rdb文件都是完整的

写时复制:父子进程共享同一片内存,父进程要修改某一部分,操作系统就复制这部分数据给他用。

因此fork时内存不会变大一倍,因此可以申请超过可用内存的空间。

如果拍快照的时候疯狂写入,那么就会导致内存占用明显变大,导致内存溢出。

换言之快照存的是,fork的那一刻的数据

AOF

把每一条redis命令记录进appendonly.aof文件。需要手动开启。

aof纯文本,记录客户端发送的原始通信协议内容。

但是会有冗余命令,因此每当达到一定条件,自动重写aof文件

重写过程只和内存中数据有关,和之前aof文件无关。

redis启动时,会逐个执行aof文件命令,把硬盘数据加载到内存中。

同步硬盘

写入硬盘,是写入了硬盘的缓存,一般操作系统30s会同步一次进入硬盘。

也可以主动要求系统,把缓存内容同步到硬盘中。

一般使用默认值,每秒同步一次即可。

第八章 集群

  • 避免单点故障

  • 要扩容

8.1复制

主从结构。主master数据库,可以读写,主要是读;从slave数据库,只读。

主数据改动会同步给从。一主可有多从,一从只能有一主。主从关系可更改。

从也可以为主,下面跟从数据库。

适合读多写少的场景。

info replictaion来查看信息

同步

一开始的同步,是主数据库异步在后台保存快照,即RDB持久化。同时把接收到的命令缓存起来。

然后复制给从数据库,从数据库从快照和命令缓存恢复。

同步过程中,请求数据的命令都回复错误。即不让读数据。

此后主数据库,就同步修改命令,给从数据库

乐观复制

允许主从之间有数据不同步,但最终会同步。

复制数据是异步的,因此会有数据不一致的时间窗口。

无硬盘复制

  • 不论有没有开rdb,快照都会拍。那么下次启动,主数据库就会以快照恢复数据。

如果没开rdb,就可能恢复了错误时间点的数据

  • 每次和数据库同步,redis都会执行一次快照,导致性能降低

无硬盘复制,初始化时,不存硬盘,直接通过网络发送给从数据库,绕开硬盘性能瓶颈。

增量复制

从数据库断开连接,之后连接上主,如果再快照走一遍,就很浪费。

  • 存主数据库的运行id,每个实例对应一个id,重启生成新的

  • 主数据库记录每个命令,放在一个积压队列里面,记录偏移量(指针)

  • 从数据库接收主数据库命令,也要记录命令的id(偏移量)

重连后

  • 判断运行id是否和自己的一致,之前是不是和自己在同步的

  • 命令偏移量比对一下,把增量命令发给从

如果不满足,就全部同步

挤压队列就是固定长度的循环队列。越长允许断线时间越长。

8.2哨兵

主挂了怎么办?哨兵自动化监控+故障恢复

如果主挂了,就选一个从当主,如果主再连上,就自动变成从。

一般一个节点一个哨兵盯着。哨兵环境尽可能模拟数据库环境。

  • 定期info获取当前数据库的信息。

    有新节点自动发现,也能获取从数据库列表,然后同样方式建立连接

  • 定期和别的哨兵沟通,分享已有信息、主数据库的配置版本

    有新哨兵就能这样发现。

  • ping其他哨兵和数据库,监控有没有停止服务。

故障处理

  1. 如果被ping的对方超时没有,就认为其 主观下线。

即从这个哨兵的视角看来它是下线了

  1. 然后就把消息同步给其他哨兵。当认为 主观下线的人超过一半,就认为 客观下线了

  2. 选举领头哨兵节点,进行故障恢复

选举方法

  • 发现客观下线的节点,告诉每个哨兵,选自己当节点

  • 如果哨兵还没选过人,就选他

  • 如果投票结果没有超过半数的,每个人参选人随机等一段时间,让别人投自己

恢复方法

停止服务的主数据库,从数据库当中挑选一个来当新的主

  • 人为设置优先级高的当选

  • 命令偏移量大,即最接近主数据库数据的当选

  • 都一样就看id小的当选

8.3 集群

每个数据库拥有全部数据,那么存储容量就会受制于内存最小的数据库。

水瓶扩容,就是客户端分片,整个数据分布在n个节点中。【有点像哈希表】

可以预分片,先规划好哪些存哪里。

Cluster

比客户端分片性能更优、更方便

  • 只能用默认0号数据库

  • 一个集群至少3个主数据库

  • 每个节点都有自己的运行ID,是集群中的身份证。每个节点都完全独立。

初始化

  • redis-trib.rb,以客户端形式ping所有节点

  • 向每个节点发送cluster meet命令,告诉其他节点的ip和port

  • 分配主从节点,主从不在一个ip,主尽量不在一个ip,容灾能力。

  • 主数据库分配插槽,哪些键归哪些节点负责

分配插槽

没规定的话,插槽连续。

设定键的时候,可以用{}包裹标签,这样就会被分配到同一个插槽当中了。同一个节点,才能支持多健的批量操作。

节点增加

给新节点发送,集群中任意一个节点的ip和port。相当于找个人引荐

其他人都能顺着找到。

找不到就跳转

类似于路由,这里找不到就跳转,重新定向。比如在同步数据之类的时候。

不过这样就增加了请求次数,因此可以加个缓存。

故障恢复

定期抽取5节点,选择最久没ping的ping一下

  • 一段时间内没回复,人为疑似下线(主观下线)

  • 如果整个集群一半都认为下线,就标记为下线,启动故障恢复。

  • 下线的从数据库里面,找一个从,变成主。也是用哨兵的那个算法

第九章 管理

9.1 安全

没有多少安全工作。需要运行在“可信环境”中。redis默认接受任何地址发来的请求。

生产环境中也不能外界直接连接到redis服务器,需要应用程序进行中转。

密码

配置密码,每次链接都要发送密码。

但redis性能高且密码错误后不会主动延迟。所以可以穷举密码,一秒尝试十几万个。

主数据库设置了密码,从数据库要配置相应密码,就能自动认证。

通信协议

  • 简单协议,就是用空格断句,平常命令行敲的。

  • 统一请求回复,AOF和主从复制的统一请求协议

返回值是一样的

9.3第三方管理工具

  • 耗时命令日志slow log

  • monitor,调试和纠错,监控所有命令

  • rdbtools,快照文件分析,到处json数据、占用内存情况等。

Previous安卓脚本Nextjs 原型链

Last updated 5 years ago

Was this helpful?

image-20191119105402225

image.png