Redis总结

redis数据结构

  • String(字符串)

    • string类型是Redis最基本的数据类型,一个键最大能存储512MB
    • value其实不仅是String,也可以是数字,可做数值计算
    • 常用命令: get、set、incr、decr mget
  • List(列表)

    • list在底层实现上并不是数组,而是链表,按照插入顺序排序,可以在头部和尾部插入新元素
    • 优点是插入快,缺点是查找慢
    • 常用命令: lpush,rpush,lpop,rpop,lrange
    • 应用场景:
      • 消息队列
      • 利用LRANGE还可以很方便的实现分页的功能
      • 在博客系统中,每篇博文的评论也可以存入一个单独的list中
      • 最新消息
      • 排行榜
  • Set(集合)

    • Set是string类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)
    • 相关操作: 添加新元素、删除已有元素、取交集、取并集、取差集等
    • 常用命令: sadd,srem,spop,sdiff ,smembers,sunion
    • 应用场景:
      • 利用集合的求交集、并集、差集等操作可以实现,共同好友、二度好友、共同关注等功能
      • 利用唯一性,可以统计访问网站的所有独立IP
      • 好友推荐的时候,根据 tag 求交集,大于某个 threshold 就可以推荐
      • QQ有一个社交功能叫做“好友标签”,比如“大美女”、“土豪”、“欧巴”
  • zset(sorted set:有序集合)

    • 不允许重复,有序集合中的每个元素都关联一个序号(score),这便是排序的依据
    • 常用命令: zadd,zrange,zrem,zcard
    • 实现方式: 内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单
    • 应用场景: 带有权重的元素,比如一个游戏的用户得分排行榜
  • Hash(哈希)

    • 它是一个string类型的field和value的映射表,hash特别适合用于存储对象

    • Redis的Hash实际是内部存储的Value为一个HashMap, 并提供了直接存取这个Map成员的接口, 如: hmset user:001 name “李三” age 18 birthday “20010101” 。也就是说,Key仍然是用户ID,value是一个Map,也就是通过 key(用户ID) + field(属性标签) 实现

    • Redis 的 Hash 结构可以像在数据库中 Update 一个属性一样只修改某一项属性值

    • 常用命令: hget,hset,hgetall

    • 实现方式: Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht

    • 应用场景: 比如一个用户要存储其全名、姓氏、年龄等等,就很适合使用哈希

Redis的持久化

  • RDB(Redis DataBase)

    • 是将redis某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法(非增量的)
    • redis会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。正是这种特性,让我们可以随时来进行备份,因为快照文件总是完整可用的
    • 优点: 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效
    • 缺点: 如果对数据的完整性非常敏感,那么RDB方式就不太适合,因为即使你每5分钟都持久化一次,当redis故障时,仍然会有近5分钟的数据丢失
  • AOF(Append Only File)

    • AOF方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍,就这么简单
    • AOF持久化策略是每秒钟记录一次,在这种情况下,redis仍然可以保持很好的处理性能,即使redis故障,也只会丢失最近1秒钟的数据
    • redis提供了AOF文件重写(rewrite)机制,即当AOF文件的大小超过所设定的阈值时,redis就会启动AOF文件的内容压缩
    • 缺点: AOF文件要比RDB文件的体积大。而且,AOF方式的恢复速度也要慢于RDB方式

Redis的主从同步

  • 像MySQL一样,redis是支持主从同步的,而且也支持一主多从以及多级从结构
  • 主从同步原理:
    • 从服务器会向主服务器发出SYNC指令,当主服务器接到此命令后,就会调用BGSAVE指令来创建一个子进程专门进行数据持久化工作,也就是将主服务器的数据写入RDB文件中。在数据持久化期间,主服务器将执行的写指令都缓存在内存中
    • 在BGSAVE指令执行完成后,主服务器会将持久化好的RDB文件发送给从服务器,从服务器接到此文件后会将其存储到磁盘上,然后再将其读取到内存中。这个动作完成后,主服务器会将这段时间缓存的写指令再以redis协议的格式发送给从服务器
    • 即使有多个从服务器同时发来SYNC指令,主服务器也只会执行一次BGSAVE,然后把持久化好的RDB文件发给多个从服务器
    • 在2.8版本之后,redis支持了效率更高的增量同步策略,即主服务器会在内存中维护一个缓冲区,缓冲区中存储着将要发给从服务器的内容。如果出现网络瞬断,重新连接好以后,从服务器会请求增量数据,主服务器就会向从服务器发送增量内容

redis的事务处理

  • 事务命令
    • multi 用来组装一个事务;–标记开始!!!
    • exec 用来执行一个事务;
    • discard 用来取消一个事务;
    • watch 用来监视一些key,一旦这些key在事务执行之前被改变,则取消事务的执行。
  • 原理
    • redis是单线程处理所有client请求
    • redis保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令
    • 非事务情况下,redis在接收一个命令后会立即处理并返回处理结果;但在开启事务之后,命令并不立即执行,而是先放到一个队列中。当接收到exec命令后,redis会顺序的执行队列中的所有命令。并将所有命令的执行结果打包到一起返回给client,然后事务结束
    • redis从2.1支持乐观锁实现CAS(check and set)操作,可以显示使用watch对某个key加锁。watch的key对整个连接有效,如果连接断开,则监视和事务都会被自动清除。当被watch的key在multi命令之前被修改,则整个事务将跳出,exec命令将返回nil

redis的哨兵(Sentinel)监控

  • 哨兵(sentinel):哨兵是一个分布式系统,你可以在一个架构中运行多个哨兵进程,这些进程使用流言协议(gossipprotocols)来接收关于Master是否下线的信息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master

  • 虽然哨兵(sentinel) 是出自一个单独的可执行文件 redis-sentinel ,但实际上它只是一个运行在特殊模式下的 Redis 服务器,你可以在启动一个普通 Redis 服务器时通过给定 --sentinel 选项来启动哨兵(sentinel)

  • 主观宕机: 每个哨兵会向其它哨兵、master、slave定时发送消息,以确认对方是否”活”着, 如果发现对方在指定时间(可配置)内未回应,则暂时认为对方已挂

  • 客观宕机: 若“哨兵群”中的多数sentinel,都报告某一master没响应,系统才认为该master"彻底死亡",通过一定的vote(选举)算法,从剩下的slave节点中,选一台提升为master,然后自动修改相关配置

  • 哨兵(sentinel)执行以下三个任务

    • 监控(Monitoring): 哨兵(sentinel) 会不断地检查你的Master和Slave是否运作正常
    • 提醒(Notification):当被监控的某个 Redis出现问题时, 哨兵(sentinel) 可以通过 API 向管理员或者其他应用程序发送通知
    • 自动故障迁移(Automatic failover):当一个Master不能正常工作时,哨兵(sentinel) 会开始一次自动故障迁移操作,它会将失效Master的其中一个Slave升级为新的Master, 并让失效Master的其他Slave改为复制新的Master; 当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用Master代替失效Master

跨jvm的id生成器

谈到这个话题,首先要知道redis-server端是单线程来处理client端的请求的。这样来实现一个id生成器就非常简单了,只要简单的调用jdeis.incr(key);就搞定了。你或许会问,incr是原子操作吗,能保证不会出现并发问题吗,前面说过,server端是单线程处理请求的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值