redis内存存储,速度极快

丰富的附件功能

1.持久化功能:降存储在内存的数据保存到硬盘
2.发布与订阅:将消息同时分发给多个客户端
3.过期键功能:为键设置一个过期时间,让它在指定的时间之后自动被删除。
4.事务功能:原子地执行多个操作,并提供乐观锁功能,保证处理数据时的安全性。
5.脚本功能:在服务器端原子地执行多个操作,完成复杂的功能,并减少客户端与服务器之间的通信往返次数。
6.复制:为指定的 Redis 服务器创建一个或多个复制品,用于提升数据安全性,并分担读请求的负载。
7.Sentinel:监控 Redis 服务器的状态,并在服务器发生故障时,进行自动故障转移。
8.集群:创建分布式数据库,每个服务器分别执行一部分写操作和读操作。

1.1设置字符串键值

*SET key value
例:
redis> set msg "hellow world"
OK
redis> get msg
hellow world *SET key value [NX|XX]
SET 命令还支持可选的 NX 选项和 XX 选项:
• 如果给定了 NX 选项,那么命令仅在键 key 不存在的情况下,才进行设置操作;如果键 key 已经存在,那么 SET ... NX 命令不做动作(不会覆盖旧值)。
• 如果给定了 XX 选项,那么命令仅在键 key 已经存在的情况下,才进行设置操作;如果键 key 不存在,那么 SET ... XX 命令不做动作(一定会覆盖旧值)。
在给定 NX 选项和 XX 选项的情况下,SET 命令在设置成功时返回 OK ,设置失败时返回 nil 。
例:
redis> SET nx-str "this will fail" XX # 键不存在,指定 XX 选项导致设置失败
(nil)
redis> SET nx-str "this will success" NX # 键不存在,所以指定 NX 选项是可行的
OK
redis> SET nx-str "this will fail" NX # 键已经存在,指定 NX 选项导致设置失败
(nil)
redis> SET nx-str "this will success again!" XX # 键已经存在,指定 XX 选项是可行的
OK

* MSET KEY VALUE
一次设置多个值
* MGET key
一次获取多个值
*INCRBY key increment
将 key 所储存的值加上增量 increment ,命令返回操作执行之后,键 key 的当前值。 *DECRBY key decrement
将 key 所储存的值减去减量 decrement ,命令返回操作执行之后,键 key 的当前值。 例:
累计阅读量
* 存储二进制数(暂时未弄明白)

例:
统计在线人数

1.2 散列

存储多个域值对
1.一个散列由多个域值对(field-value pair)组成。
2.同一个散列里面的每个域必 须是独一无二、各不相同的,而域的值则没有这一要求,不同域的值可以是重复的。
3.通过命令,用户可以对散列执行设置域值对、获取域的值、检查域是否存在等操作,也可以 让 Redis 返回散列包含的所有域、所有 值或者所有域值对。 * HSET key field value
redis> HSET message "id" 10086 * HSETNX key field value
如果散列键 key 中,域 field 不存在(也即是,还没有与之相关联的值),那么关联给定的域值对 field 和value 。
redis> HSETNX message "content" "Good morning, jack!"
(integer) 1 * HMSET key field value [field value ...]
在散列键 key 中关联多个域值对,相当于同时执行多个 HSET 。
redis> HMSET message "id" 10086 "sender" "peter" "receiver" "jack"
OK * HMGET key field [field ...]
返回散列键 key 中,一个或多个域的值,相当于同时执行多个 HGET 。
redis> HMGET message "id" "sender" "receiver"
1) "10086"
2) "peter"
3) "jack" * HKEYS key 返回散列键 key 包含的所有域。
* HVALS key 返回散列键 key 中,所有域的值。
* HGETALL key 返回散列键 key 包含的所有域值对。 

2.1 数据库管理

面向数据库的操作
dbsize、 select、flushdb/flushall命令 1.切换数据库 ,Redis默认有16个数据库,databases 16
select dbIndex
127.0.0.1:6379>select 15
OK
127.0.0.1:6379[15]> get hello
world
//一般建议只使用一个db,在cluster模式下,只允许使用0号数据库 2.flushdb/flushall命令用于清除数据库, 两者的区别的是flushdb只清除当
前数据库, flushall会清除所有数据库。

3.1慢查询分析

slowlog-log-slower-than
单位是微秒(1秒=1000毫秒=1000000微秒),默认值是10000
如果slowlog-log-slower-than=0会记录所有的命令, slowlog-log-slowerthan<0对于任何命令都不会进行记录。 slowlog-max-len
slowlog-max-len只是说明了慢查询日志最多存储多少条 slowlog get [n]:获取慢查询日志
虽然慢查询日志是存放在Redis内存列表中的, 但是Redis并没有暴露这个列表的键 对表做清理
127.0.0.1:6379> slowlog len
(integer) 45
127.0.0.1:6379> slowlog reset
OK
127.0.0.1:6379> slowlog len
(integer) 0

3.2 Redis Shell
Redis提供了redis-cli、 redis-server、 redis-benchmark等Shell工具

redis-cli命令的一些参数
1. -r(repeat) 选项代表将命令执行多次
$ redis-cli -r 3 ping
PONG
PONG
PONG 2.-i(interval) 选项代表每隔几秒执行一次命令, 但是-i选项必须和-r选
项一起使用,-i单位是秒,毫秒可以用0.1(100毫秒)
$ redis-cli -r 5 -i 1 ping
PONG
PONG
PONG
PONG
PONG 3.-x选项代表从标准输入(stdin) 读取数据作为redis-cli的最后一个参

$ echo "world" | redis-cli -x set hello
OK

4.6 客户端案例分析

1. 现象

redis持久化备份RDB的原理

1) 执行bgsave命令, Redis父进程判断当前是否存在正在执行的子进程, 如RDB/AOF子进程, 如果存在bgsave命令直接返回。
2) 父进程执行fork操作创建子进程, fork操作过程中父进程会阻塞, 通过info stats命令查看latest_fork_usec选项, 可以获取最近一个fork操作的耗
时, 单位为微秒。
3) 父进程fork完成后, bgsave命令返回“Background saving started”信息
并不再阻塞父进程, 可以继续响应其他命令。
4) 子进程创建RDB文件, 根据父进程内存生成临时快照文件, 完成后对原有文件进行原子替换。 执行lastsave命令可以获取最后一次生成RDB的
时间, 对应info统计的rdb_last_save_time选项。
5) 进程发送信号给父进程表示完成, 父进程更新统计信息, 具体见info Persistence下的rdb_*相关选项。
备份RDB的fork()
核心内容点一:fork()用于创建一个子进程,注意是子进程,不是子线程。fork()出来的进程共享其父类的内存数据。
二:仅仅是共享fork()出子进程的那一刻的内存数据,后期主进程修改数据对子进程不可见,同理,子进程修改的数据对主进程也不可见。
三:子进程B出问题了,对我主进程A完全没影响,我依然可以对外提供服务,但是主进程挂了,子进程也必须跟随一起挂。这一点有点像守护线程的概念。
Redis正是巧妙的运用了fork()这个牛逼的api来完成RDB的持久化操作。
比如:A进程fork()了一个子进程B,那么A进程就称之为主进程,这时候主进程子进程所指向的内存空间是同一个,所以他们的数据一致。
但是A修改了内存上的一条数据,这时候B是看不到的,A新增一条数据,删除一条数据,B都是看不到的。
思考:子进程与Redis主进程共享同一份内存空间,所以子进程可以搞他的rdb文件持久化工作,主进程又能继续他的对外提供服务,二者互不影响。
我们说了他们之后的修改内存数据对彼此不可见,但是明明指向的都是同一块内存空间,这之间是怎么实现的?->copyonwritefork() copyonwritefork()
主进程fork()子进程之后,内核把主进程中所有的内存页的权限都设为read-only,然后子进程的地址空间指向主进程,这也就是共享了主进程的内存。
当主进程要修改内存中的某个值时,CPU硬件检测到页是read-only,于是触发了页异常中断,陷入内核的一个中断例程,中断例程中内核会把触发异常的页复制一份,
主进程在新的内存块修改key值并把指针指向新块地址,子进程共享的内存块和对应的指针没有变。

4.redis缓存穿透、缓存击穿、缓存雪崩

缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。

缓存击穿:这个跟缓存雪崩有点像,但是又有一点不一样,缓存雪崩是因为大面积的缓存失效,打崩了DB,而缓存击穿不同的是缓存击穿是指一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,
当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞 缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。
//举个简单的例子:如果所有首页的Key失效时间都是12小时,中午12点刷新的,我零点有个秒杀活动大量用户涌入,假设当时每秒 6000 个请求,
本来缓存在可以扛住每秒 5000 个请求,但是缓存当时所有的Key都失效了。此时 1 秒 6000 个请求全部落数据库,数据库必然扛不住,它会报一下警,真实情况可能DBA都没反应过来就直接挂了。
此时,如果没用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。这就是我理解的缓存雪崩。

5.redis集群的部署和管理

当遇到单机内存、并发、流量等瓶颈,则可采用Cluster集群

Redis Cluster采用虚拟槽分区,所有的键根据哈希函数映射到0~16383整数槽内,计算公式:slot=CRC16(Key)&16383。每个节点负责维护一部分呢槽以及槽所映射的键值数据。

Redis虚拟槽分区的特点:
1.解耦数据和节点之间的关系,简化了节点扩容和收缩难度
2.节点自身维护槽的映射关系,不需要客户端或者代理服务维护槽分区元数据
3.支持节点、槽、键之间的映射查询用于数据路由、在线伸缩

集群功能限制

1.只支持同个槽中的key执行批量操作
2.只支持同个节点上的key进行事务操作
3.不能将key的键值对象映射到不同的节点
4.不支持多数据空间
5.复制结构只支持一层

搭建集群

1)准备节点

·节点数至少6个,才能组成完整高可用的集群
·每个节点开启配置cluster-enabled yes,让redis运行在集群模式下
·集群所有节点统一目录,一般划分三个目录:conf、data、log,分别存放配置、数据和日志
=======================================
集群相关配置如下:
# 节点端口
port 6379
# 开启集群模式
cluster-enabled yes
# 节点超时时间,单位毫秒
cluster-node-timeout 15000
# 集群内部配置文件
cluster-config-file "nodes-6379.conf"

其他配置和单机模式一致即可,配置文件命名规则redis-{port}.conf
=======================================

集群模式的redis除了原有的配置文件,添加了一份集群配置文件。当集群节点信息发生变化,如添加节点、节点下线、故障转移等,

节点都会自动保存集群状态到配置文件中。集群配置文件中的节点ID不同于运行ID,节点ID在集群初始化时只创建一次。

现阶段每个节点只能识别自己的节点信息(cluster nodes,只有自己信息)

2)节点握手

通过Gossip协议彼此通信
节点握手
127.0.0.1:6379>CLUSTER MEET 127.0.0.1 6380
127.0.0.1:6379>CLUSTER MEET 127.0.0.1 6381
127.0.0.1:6379>CLUSTER MEET 127.0.0.1 6382
127.0.0.1:6379>CLUSTER MEET 127.0.0.1 6383
127.0.0.1:6379>CLUSTER MEET 127.0.0.1 6384

3)分配槽

Linux命令行执行:
# redis-cli -h 127.0.0.1 -p 6379 cluster addslots {0..5461}
# redis-cli -h 127.0.0.1 -p 6380 cluster addslots {5462..10922}
# redis-cli -h 127.0.0.1 -p 6381 cluster addslots {10923..16383} 设置主节点的从节点,从节点执行,cluster replicate {nodeId} ,nodeId为主节点集群id:
127.0.0.1:6382>cluster replicate cfb28ef1d...d24566744411e
OK
127.0.0.1:6383>cluster replicate 8e41673d59c9...ce733345b3e8f1
OK
127.0.0.1:6384>cluster replicate 40b8d09d4429...fc8fcd153446746
OK

【集群也可以用redis-trib.rb搭建,依赖Ruby】

最新文章

  1. java享元模式(flyweight)
  2. CGAL4.1在VS2010上配置
  3. 在Win2008上运行ASP.NET 1.1程序
  4. Count Colour_poj2777(线段树+位)
  5. C++ builder 2010 操作Excel表格的编程实现
  6. Asp.net中使用资源文件实现网站多语言
  7. iOS网络编程-ASIHTTPRequest框架同步请求-备用
  8. tag_on_failure =&gt; [] # prevent default _grokparsefailure tag on real records
  9. C++ 一些容易忽略的基本点
  10. IntelliJ IDEA(五) :Settings(中)
  11. 贝叶斯、朴素贝叶斯及调用spark官网 mllib NavieBayes示例
  12. 从npm 角度理解 mvn 的 pom.xml
  13. Create ISO library over NFS for XEN server templates
  14. PHP_CodeSniffer HG 服务端部署篇
  15. EPPlus实战篇——Excel读取
  16. XML.libXml2_ZC
  17. NGUI实现UITexture的UV滚动
  18. FFMpeg笔记(六) 滤镜命名规则及使用libavfilter对视频尺寸进行裁切
  19. HDU-4850 Wow! Such String! (构造)
  20. SpringMVC &amp; SpringBoot小记

热门文章

  1. pg_basebackup恢复:unrecognized configuration parameter &quot;restore_command&quot;
  2. .net core操作MongoDB
  3. python网络爬虫数据解析之正则
  4. 升级csproj文件为vs2017工程格式(SDK样式)
  5. Linux c 检测U盘挂载路径方法
  6. java 进阶P-3.7
  7. 移动 WEB 开发布局方式 ---- rem 适配布局
  8. 构建api gateway之 健康检查
  9. 一次生产环境CPU占用高的排查
  10. SpringBoot 三大开发工具,你都用过么?