Redis用途

1.缓存

  Redis提供了键值过期时间设置, 并且也提供了灵活控制最大内存和内存溢出后的淘汰策略。 可以这么说, 一个合理的缓存设计能够为一个网站的稳定保驾护航。

2.排行榜系统

 Redis提供了列表和有序集合数据结构, 合理地使用这些数据结构可以很方便地构建各种排行榜系统。

3.计数器应用

Redis适用于高并发的递增、递减功能

递增指令:incr(默认从0开始)

递减指令:decr(默认从0开始,递减会出现负数,这点跟memcache不一样,mc到0)

4.社交网络

赞/踩、 粉丝、 共同好友/喜好、推送、下拉刷新等是社交网站的必备功能,由于社交网站访问量通常比较大,而且传统的关系型数据不太适合保存这种类型的数据,

Redis提供的数据结构可以相对比较容易地实现这些功能。

5.消息队列系统

Redis提供了发布订阅功能和阻塞队列的功能,虽然和专业的消息队列比还不够足够强大, 但是对于一般的消息队列功能基本可以满足。

6.共享Session

redis 递增id redis 递增_Redis

7.限速

但是为了短信接口不被频繁访问, 会限制用户每分钟获取验证码的频率, 例如一分钟不能超过5次。

redis 递增id redis 递增_Redis_02

一些网站限制一个IP地址不能在一秒钟之内访问超过n次也可以采用类似的思路。

 API的理解和使用

Redis发展历程中提供了move、 dump+restore、 migrate三组迁移键的方法。

Redis默认配置中是有16个数据库,推荐使用0号数据库?

假设databases=16, select0操作将切换到第一个数据库, select15选择最后一个数据库, 但是0号数据库和15号数据库之间的数据没有任何关联, 甚至可以存在相同的键。

Redis3.0中已经逐渐弱化这个功能, 例如Redis的分布式实现Redis Cluster只允许使用0号数据库, 只不过为了向下兼容老版本的数据库功能,该功能没有完全废弃掉。

Redis是单线程的。 如果使用多个数据库, 那么这些数据库仍然是使用一个CPU, 彼此之间还是会受到影响的。

多数据库的使用方式, 会让调试和运维不同业务的数据库变的困难,假如有一个慢查询存在, 依然会影响其他数据库, 这样会使得别的业务方定位问题非常的困难。

部分Redis的客户端根本就不支持这种方式。 即使支持, 在开发的时候来回切换数字形式的数据库, 很容易弄乱。

笔者建议如果要使用多个数据库功能, 完全可以在一台机器上部署多个Redis实例, 彼此用端口来做区分, 因为现代计算机或者服务器通常是有多个CPU的。

这样既保证了业务之间不会受到影响,又合理地使用了CPU资源。

scan命令可以解决keys命令可能带来的阻塞问题, 同时Redis还提供了hscan、 sscan、 zscan渐进式地遍历hash、 set、 zset。

小功能大用处

 

redis 递增id redis 递增_Redis_03

redis 递增id redis 递增_运维_04

redis 递增id redis 递增_Redis_05

 

redis 递增id redis 递增_数据结构与算法_06

Redis提供了简单的事务, 之所以说它简单, 主要是因为它不支持事务中的回滚特性。

 

redis 递增id redis 递增_数据结构与算法_07

客户端

 

redis 递增id redis 递增_数据库_08

redis 递增id redis 递增_数据结构与算法_09

redis 递增id redis 递增_数据结构与算法_10

 持久化

Redis提供了两种持久化方式: RDB和AOF。

RDB持久化是把当前进程数据生成快照保存到硬盘的过程, 触发RDB持久化过程分为手动触发和自动触发。

手动触发分别对应save和bgsave命令:save命令: 阻塞当前Redis服务器, 直到RDB过程完成为止, 对于内存比较大的实例会造成长时间阻塞, 线上环境不建议使用。

bgsave命令: Redis进程执行fork操作创建子进程, RDB持久化过程由子进程负责, 完成后自动结束。 阻塞只发生在fork阶段, 一般时间很短。

显然bgsave命令是针对save阻塞问题做的优化。 因此Redis内部所有的涉及RDB的操作都采用bgsave的方式, 而save命令已经废弃。

针对RDB不适合实时持久化的问题, Redis提供了AOF持久化方式来解决。

AOF( append only file) 持久化: 以独立日志的方式记录每次写命令,重启时再重新执行AOF文件中的命令达到恢复数据的目的。

AOF的主要作用是解决了数据持久化的实时性, 目前已经是Redis持久化的主流方式。

开启AOF功能需要设置配置: appendonly yes, 默认不开启。

redis 递增id redis 递增_数据结构与算法_11

Redis单线程架构导致无法充分利用CPU多核特性, 通常的做法是在一台机器上部署多个Redis实例。

复制

redis 递增id redis 递增_redis 递增id_12

redis 递增id redis 递增_数据库_13

redis 递增id redis 递增_redis 递增id_14

拓扑

redis 递增id redis 递增_数据库_15

redis 递增id redis 递增_redis 递增id_16

redis 递增id redis 递增_数据结构与算法_17

redis 递增id redis 递增_数据结构与算法_18

 

redis 递增id redis 递增_Redis_19

redis 递增id redis 递增_数据库_20

Redis的噩梦: 阻塞

 

redis 递增id redis 递增_数据库_21

内存

 

redis 递增id redis 递增_数据库_22

redis 递增id redis 递增_redis 递增id_23

哨兵

 

redis 递增id redis 递增_数据库_24

redis 递增id redis 递增_数据结构与算法_25

redis 递增id redis 递增_运维_26

redis 递增id redis 递增_数据库_27

redis 递增id redis 递增_数据库_28

redis 递增id redis 递增_数据库_29

redis 递增id redis 递增_Redis_30

redis 递增id redis 递增_数据结构与算法_31

redis 递增id redis 递增_数据结构与算法_32

redis 递增id redis 递增_运维_33

redis 递增id redis 递增_redis 递增id_34

redis 递增id redis 递增_数据结构与算法_35

集群

 Redis Cluster是Redis的分布式解决方案, 在3.0版本正式推出, 有效地解决了Redis分布式方面的需求。 当遇到单机内存、 并发、 流量等瓶颈时, 可以采用Cluster架构方案达到负载均衡的目的。

 

redis 递增id redis 递增_数据结构与算法_36

redis 递增id redis 递增_Redis_37

1.节点取余分区

2.一致性哈希分区

3.虚拟槽分区

 

redis 递增id redis 递增_Redis_38

redis 递增id redis 递增_数据库_39

 

redis 递增id redis 递增_数据结构与算法_40

redis 递增id redis 递增_运维_41

redis 递增id redis 递增_数据结构与算法_42

缓存设计

 

redis 递增id redis 递增_运维_43

缓存穿透

缓存穿透是指查询一个根本不存在的数据, 缓存层和存储层都不会命中。(攻击者利用大量不存在的验证ID进行请求,导致了缓存穿透,引起后端数据库压力骤增而崩溃。)

redis 递增id redis 递增_Redis_44

有效地解决缓存穿透

    有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,

  一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外也有一个更为简单粗暴的方法(我们采用的就是这种),

  如果一个查询返回的数据为空(不管是数 据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

redis 递增id redis 递增_运维_45

雪崩优化

redis 递增id redis 递增_运维_46

Redis监控运维云平台CacheCloud

 

redis 递增id redis 递增_运维_47

其他

批量操作命令可以有效提高开发效率

批量设置值

mset key value [key value ...]

批量获取值

mget key [key ...]

redis怎样更新值而不重置过期时间



TimeSpan spanTimeoutLeft = redisExpertCodesCacher.KeyTimeToLive(loginHelper.UserName);//获得key目前的剩余过期时间
  bool b = redisExpertCodesCacher.SetAddExpertCode(loginHelper.UserName, q, spanTimeoutLeft);//使用Set存储 是否需要判断学者代码是否存在?如果不存在则添加