redis

简介

为什么这么快?

  • 基于内存,不受硬盘io
  • 数据结构,操作简单
  • 单线程(主线程(io时间处理、集群协调等)是单线程,所有读写请求由一个线程处理)。
    可以处理并发吗?
  • 多路io复用(根据不同系统选择不同多路复用函数,优先选择O(1),select保底)

memchace区别

  • memcache
    • 支持简单数据类型
    • 不支持持久化
    • 不支持分片
    • 不支持主从
  • redis
    • 类型丰富
    • 支持持久化
    • 支持主从
    • 支持分片

类型&命令

String

set strkey “这是一个字符串”

get strkey

命令含义使用场景
set key value设定指定的值
get key获取指定key的值
getrange key start end返回 key 中字符串值的子字符
getset key value将给定 key 的值设为 value ,并返回 key 的旧值(old value)
mget key1 key2 …获取所有(一个或多个)给定 key 的值
strlen key返回 key 所储存的字符串值的长度
mset key value key value同时设置一个或多个 key-value 对
incr key对应key的值加1记录每天用户访问多少次,用户id+时间作为键,每访问一次incr就好

一个键最大能存储512MB

hash

hmset hashKey feild1 “hello” feild2 “world”

hget hashKey feild1

每个 hash 可以存储 2^32 -1 键值对(40多亿)

命令含义
hdel key field1 field2 …删除一个或多个哈希表字段
hexists key field查看哈希表key中,指定的字段是否存在
hget key field获取存储在哈希表中指定字段的值
hgetall key获取在哈希表中制定key的所有字段和值
hkeys key获取所有哈希表的字段
hlen key获取哈希表中字段的数量
hmget key field1 field2 …获取所有给定字段的值
hmset key field1 value1 field2 value2同时将多个field-value设置到哈希表key中
hset key field value将哈希表key中的字段field的值设置为value
hvals key获取哈希表中所有值

List

字符串列表,插入顺序,可以在列表头部或者尾部插入一个元素

lpush listKey “one”

lpush listKey “two”

lrange listKey 0 10

列表最多可存储 2^32 - 1 元素 (4294967295, 每个列表可存储40多亿)。

命令含义
blpop key1 key2 timeout移出并获取列表的第一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
brpop key1 key2 timeout移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
brpoppush sou des timeout从列表中弹出一个值,将弹出的元素插入到另外一个列表中并返回他;如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
lindex key index通过索引获取列表中的元素
linsert key before/after pivot value在列表的元素前或者后插入元素
llen key获取列表长度
lpop key移出并获取列表的第一个元素
lpush key value1 value2.。。将一个或多个值插入到列表头部
lpushx key value将一个值插入到已存在的列表头部
lrange key start stop获取列表制定范围内的元素(后进先出)
lrem key count value移除列表元素
lset key index value通过索引设置列表元素的值
rpop key移除列表的最后一个元素,返回值为移除的元素
rpoplpush sou des移除列表的最后一个元素,并将该元素添加到另外一个列表返回
rpush key value1 value2 。。。在列表中添加一个或多个值
rpushx key value为已存在的列表添加值

set

无序集合,元素唯一

集合中最大的成员数为 232 - 1(4294967295, 每个集合可存储40多亿个成员)。

sadd setKey “one”

sadd setKey “two”

smembers setKey

命令含义
sadd key member1 member2 。。。向集合中添加一个或多个成员
scard key获取集合成员数
sdiff key1 key2 。。。返回给定所有集合的差集微博存储用户的关注或者粉丝,方便计算共同关注等
sdiffstore des key1 key2 。。。返回给定所有集合的差集并存储再des中
sinter key1 key2 。。。返回所有给定集合的交集
sinterstore des key1 key2 。。返回所有给定集合的交集并存储在des中
sismemner key member判断member元素是否存在集合key的成员
smembers key返回集合中所有成员
smove source des member将member元素从sou移到des集合
spop key移除并返回集合中的一个随机元素
srem key member1 member2 。。。移除集合中的一个或多个成员
sunion key1 key2 。。。返回所有给定集合的并集
sunionstore des key1 key2 。。。所有给定集合的并集并存储在des集合中

zset

有序集合,元素唯一

不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

zadd zsetKey 0 “one”

zadd zsetKey 0 “two”

zrangebyscore zsetKey 0 100

命令含义
zadd key score1 member1 score2 member2 。。。向有序集合中添加一个或多个成员,或者更新已存在成员的分数
zcard key获取集合成员数
zcount key min max计算指定区间分数的成员数
zrank key member返回有序集合中指定成员的索引
zrem key member。。。移除有序集合中一个或多个成员
zscore key member返回有序集中成员的分数

键命令

命令含义
del key删除键
dump key序列化key
exists key判断key是否存在
Keys pattern查找所有符合条件的key一次性返回所有满足的key,可能导致阻塞服务器
TYPE key返回key所存储的值的类型
scan surdor match pattern count xx以0开始迭代,每次输入上次返回的游标值,最后返回0结束,每次返回的数量不确定,大概率符合count参数127.0.0.1:6379> scan 0 match my* count 1 1) “10” 2) 1) “myset” 127.0.0.1:6379> scan 0 match my* count 1
  • 海量数据找出固定前缀的key?

HyperLogLog

做基数统计的算法,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。比如数据集 {1, 3, 5, 7, 5, 7, 8}, 那么这个数据集的基数集为 {1, 3, 5 ,7, 8}, 基数(不重复元素)为5。 基数估计就是在误差可接受的范围内,快速计算基数。

命令含义
pfadd key element1 element2.。。添加指定元素到HyperLogLog中
pfcount key1 key2.。。返回给定HyperLogLog的基数估算值
pfmerge deskey sourcekey1 sourcekey2.。。多个合并成一个

Geo

存储地理位置信息

发布订阅

redis发布订阅是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。redis客户端可以订阅任意数量的频道。

命令含义
psubscribe pattern pattern。。。订阅一个或多个符合给定模式的频道
pubsub subcommand argument查看订阅与发布系统状态
publish channel message将信息发送到指定的频道
punsubscribe pattern pattern。。。退订所有给定模式的频道
subscribe channel channel。。。订阅给定的一个或多个频道的信息
unsubscribe channel channel…指退订给定的频道

事务

一次执行多个命令,并且:

  • 批量操作在发送exec命令前被放入队列缓存
  • 收到exec命令后进入事务执行,事物中任意命令执行失败,其他命令依然被执行
  • 在事物执行过程中,其他客户端提交的命令请求不会插入到事物执行命令序列中
命令含义
discard取消事务,放弃执行事务块所有命令
exec执行所有事务块内的命令
multi标记一个事务块的开始
unwatch取消watch命令对所有key的监视
watch key key。。。监视一个或多个key,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

分布式锁

访问共享资源时,防止彼此干扰
需要解决问题:

  • 互斥性
  • 安全性
  • 死锁
  • 容错

setnx key value 如果key不存在,设置成功,如果key已存在,不成功

如何解决长期有效的问题?

expire key timeout

原子性得不到满足

例子:

long status = setnx.(key,“1”);

//执行完挂了,key一直被占用

if(status == 1){

expire.(key,10);

doWork();

}

优化:

set key value [ex sencods] [px milisencods] [nx|xx]

nx:只在键不存在时才对键进行设置操作

xx:只在键存在时才对键进行设置操作

集中处理大量过期key暂时卡顿现象,在设置key的过期时间时加个随机值。

异步队列

使用list做为队列,rpush生产消息,lpop消费消息

缺点:没有等待队列里有值就直接消费
优化:可以在应用层使用sleep机制去调用lpop重试

blpop 阻塞直到有值再消费
缺点:只有一个消费者
优化:pub/sub
缺点:无状态,无法保证到达

持久化

  • RDB(快照)持久化:保存某个时间点的全量数据快照

    • save:阻塞redis的服务进程,直到rdb文件创建完毕
    • bgsave:子进程创建rdb文件,不阻塞服务进程
    • lastsave:上次保存时间
  • 自动化触发RDB持久化的方式

    • redis.conf里配置save m n 定时触发(使用的时bgsave)
    • 主从复制时,主节点主动触发
    • 制定debug reload
    • 执行shutdown且没有开启AOF持久化
  • BGCAVE原理

    • 检查是否子进程在AOF/RDB正在执行
    • 不存在触发持久化
    • fork()
  • 缺点

    • 内存数据的全量同步,数据量大时由于I/O严重影响性能
    • 可能由于redis挂掉丢失当前到最近一次的快照时间内的数据
  • AOF持久化:保存写

  • 记录除查询以外的变更数据库状态的命令

  • 以append的方式追加到AOF文件中(增量)appendonly.aof

  • 写操作增加,日志文件越来越大?解决:日志重写

    • fork()
    • 子进程把新的AOF写到一个文件中,不依赖原来的AOF
    • 主进程持续把新的变动写到内存和原来的AOF中
    • 主进程获取子进程完成重写AOF信号,往新AOF同步增量变动
    • 使用新的AOF文件替换掉旧的
优点缺点
RDB全量数据快照,文件小,恢复快无法保存最近一次快照之后的数据
AOF可读性高,适合增量保存,不容易丢失数据文件体积大,恢复时间长
  • RDB-AOF混合持久化方式

Pipeline及主从

  • pipeline:批量执行命令,节省I/O时间
  • 主从同步机制
    • 全同步
      • slave发送sync命令到master
      • master启动一个后台进程,将redis的数据快照保存到文件中
      • master将同步期间接受到的写命令缓存起来
      • master完成写文件后将文件发送给slave
      • 使用新的rdb文件替换久的rdb文件
      • master将增量写命令发给slave
    • 增量同步
      • master接收到用户指令后,判断会否需有传播到slave
      • 将操作记录追加导AOF文件
      • 将操作传播到其他slave,1、对其主库;2、往响应缓存写入
      • 将缓存中数据发给slave
  • master挂掉不能写操作,解决:redis sentinel
    • 监控:检查主从是否正常
    • 提醒:通过API向管理或其他应用发送故障通知
    • 自动故障迁移:主从切换(流言协议Gossip)

redis集群

如何海量数据快速找到所需?

  • 一致性哈希算法:对2^32取模,将哈希值空间组成虚拟圆环。
  • 将key按相同的hash函数计算哈希值,顺时针找到最近服务器
    在这里插入图片描述
    哈希环数据倾斜问题?
  • 虚拟节点
    在这里插入图片描述

Redis Cluster

Redis Cluster是Redis官方提供的Redis集群功能。
为什么要实现?
1、主从复制不能实现高可用
2、随着用户数量增多,并发越来越多,业务需要更高的QPS,主从复制的单机QPS可能无法满足业务需求
3、服务器内存不能业务需要时,单纯的向服务器添加内存不能达到要求,此时需要充分考虑分布式需求,把数据分布到不同机器上
4、网络流量需求:业务流量超过服务器的网卡限制,可以使用分布式来进行分流
5、离线计算,需要中间环节缓冲等别的需求
虚拟槽分区
redis cluster采用虚拟槽分区,把所有的物理结点映射到[0-16383]slot上,cluster负责维护node<->slot<->value。当存放key-value时,根据哈希函数(CRC16[key]&16384)映射到0-16383槽(slot)内,共16384个槽位,每个节点维护部分槽及槽所映射的键值数据。
例如:
节点A覆盖0-5460
节点B覆盖5461-10922
节点C覆盖10923-16383

获取数据,存入一个值,按照(CRC16[key]&16384)= 6782,那么会存在结点B。当获取key是也会计算去结点B取。

新增一个主结点,从各个结点的前面各取一部分slot到D上,同样删除也是。

为了保证高可用,加了主从模式,一个主结点对应一个或多个从结点,主结点提供数据存取,从结点从主结点拉去备份,当主结点挂掉后,会选一个从结点变成主结点,保证集群不会挂掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值