Redis

Nosql概述

为什么要用nosql?(非关系型数据库)
  • 对数据库高并发读写的需求
  • 对海量数据的高效率存储和访问的需求
  • 对数据库的高可扩展性和高可用性的需求
什么是nosql

Nosql=Not Only Sql

泛指非关系型数据库,随着web2.0互联网的诞生!传统的关系型数据库很难应付web2.0时代!尤其是超大规模的高并发的社区!暴漏出很多难以克服的问题,Nosql在当今大数据的时代下飞速发展,是一个必须掌握的知识。

nosql特点
  1. 方便扩展(数据之间没有关系,便于扩展)
  2. 大数据量高性能(Redis一秒可以写8w次,读11w次,Nosql的缓存记录级,是一种细粒的缓存,性能高)
  3. 数据库类型是多样性的(不需要事先设计数据库,随去随用!如果是数据量非常大的表,很多就无法设计了)
  4. 传统的RDBMS和Nosql
传统的RDBMS
-结构化组织
-SQL
-数据和关系都在表中
-数据库定义语言
-严格的一致性
-基础的事务

Nosql
-不仅仅是sql
-没有固定的查询语言
-键值对存储,列存储,文档存储,图形数据库(社交关系)
-cap定理和base(异地多活)初级架构师!
-高性能,高可用,高并发

大数据时代的3V:

  1. 海量Volume
  2. 多样Variety
  3. 实时Velocity

大数据时代的3高:

  1. 高并发
  2. 高可拓
  3. 高性能

需要nosql+rdbms一起使用才可以

阿里云的基础架构

  1. 商品信息(名称,价格等)

Mysql

  1. 商品描述,评价(文字较多)

文档类型数据库,mongodb

  1. 图片

分布式文件系统 FastDFS

-淘宝的 TFS

-Gooale的 GFS

-Hadoop HDFS

-阿里云的 oss

  1. 商品关键字搜索

-搜索引擎 solr elasticsearch

-Iserach

  1. 商品热门信息

-内存数据库(redis Tair memache)

  1. 商品交易,外部的支付接口

三方应用

NoSQL的四大分类

kv键值对:

  • 新浪:Redis
  • 美团:Redis+Tair
  • 阿里,百度:Redis+memecache

文档型数据(bson格式和json一样):

  • mongodb(重要)
    • mongodb是一个基于分布式文件存储的数据库,c++编写的,主要用来处理大量的文档
    • mongodb是一个介于关系数据库和非关系数据库中间的产品,mongodb是非关系数据库中功能丰富,最想关系型数据库的数据库

列存储数据库

  • Hbase
  • 分布式文件系统

图关系数据库

  • 他不是存图形的,是放关系的,比如朋友圈,广告推荐等
  • Neo4j,InfoGrid

Redis入门

概述

Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

免费开源!是当下最热门的nosql技术,结构化数据库。

redis能干吗?

  1. 内存存储,持久化,内存中断电即失,所以说持久化很重要(rdb,aof)
  2. 效率高,可以用作高速缓存
  3. 发布订阅系统
  4. 地图信息分析
  5. 计时器,计数器(浏览量)

特性

  1. 多样的数据库类型

  2. 持久化

  3. 集群

  4. 事务

Redis推荐在Linux服务器上搭建

安装

window

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EejxPV2U-1591575392425)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603151145740.png)]

Linux

官方只支持Linux版本

  1. 下载安装包,连接远程服务器,用xftp将安装包传过去

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tdZ9nVDv-1591575392432)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603152759486.png)]

  2. 将安装包解压[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pl6WpjTa-1591575392434)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603152854251.png)]命令

  3. 安装环境[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5i7zsQR9-1591575392438)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603153034123.png)]

  4. make命令安装环境[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yjvv0H9C-1591575392441)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603153148556.png)]

  5. make install[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8bGa9Bf4-1591575392443)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603153422082.png)]

  6. 默认安装路径是 usr/local/bin

  7. 创建kuconfig文件,将最初解压文件中的redis.conf粘贴进去

  8. 修改redisconf,改为后台启动[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1bXOmbqS-1591575392444)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603154619329.png)]

  9. 后台启动redis[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7cohsVC7-1591575392445)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603154854941.png)]

  10. 使用redis。cli连接并测试[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aj3AtMRS-1591575392446)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603155234331.png)]

  11. 查询进程[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jtk39Bum-1591575392447)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603155507434.png)]

  12. 关闭redis服务[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A2Mohj3j-1591575392448)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603155608184.png)]

性能测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6UjM1BKO-1591575392449)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603155956877.png)]

测试 100个并发100000次:  redis-benchmark -h localhost -p 6379 -c 100 -n 100000

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XxWFjk1z-1591575392450)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603160925370.png)]

基础知识

  1. 默认有16个数据库[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YB1rjulb-1591575392451)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603162502735.png)]

默认使用第0个,可以用select进行切换

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yJVNyHvB-1591575392453)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200603162650787.png)]

查看数据库所有的key  #  keys *
清空数据库          # flushdb
清空全部数据库       #flushall 

redis是单线程的!

明白redis是很快的,官方表示,redis是基于内存操作的,cpu不是redis的性能瓶颈,redis的瓶颈是根据机器的内存和网络带宽,既然可以使用单线程来实现,就使用单线程!所有就使用了单线程了!

redis是c语言编写的,官方提供的数据为100000+的QPS,完全不比同样使用key-value的memecache差

redis为什么单线程还这么快?
  1. 误区:高性能的一定是多线程的

  2. 误区2:多线程(cpu上下文会切换)一定比单线程高

    先去cpu>内存>硬盘

    核心:redis是将所有的数据全部放在内存中,所以说使用单线程去操作效率就是最高的,多线程(cpu上下文会切换:耗时的操作!!),对应内存来说,如果没有上下文切换的效率就是最高的!多次读写都是在一个cpu上的,在内存情况下,这个方案就是最佳的

五大数据类型

Redis-Key
 keys *               #查看所有值
 set name kuangshen   #将name设置为kuangshen
 get name             #输出name的值
 exists name          #是否存在name值
 expire name 10       #设置name值的过期时间
 ttl name             #查看name的过期时间
 move name 1          #将name移动到数据库1
 type name            #查看类型
String
append name "hello"   #给name增加字符串,如果name不存在,就相当于set 
incr/decr index       #index大小增加一减小一
incrby/decrby index 10       #index增加10减少10
getrange name 1 3        #得到name字符串1-3
getrange name 0 -1       #得到全部字符串
setrange name 1 xx       #将name中第一个字符后两个改为xx
setex name 30 “hello”    #设置name过期时间30秒
setnx(set if not exist) #如果不存在name,则可以设置name值,如果name已经存在,那么name则会设置不成功(分布式锁中使用)
mset k1 v1 k2 v2 k3 v3   #批量设置值
mget k1 k2 k3            #批量获取值
msetnx k1 v1 k4 v4       #msetnx是一个原子操作,要么一起成功,要么一起失败

#对象
set user:1{name:zhangsan,age:3}
mset user:1:name zhangsan user:1:age 2
mget user:1:name user:1:age

getset db redis  #先获得,后设置
  • 计数器

  • 统计多单位的数量

  • 粉丝数

  • 对象缓存存储

List

在redis中我们可以把list玩成 栈,队列,阻塞队列

所有的list命令都是以l开头的

lpush list one
lpush list two
lpush list three
lrange list 0 -1       #得到list中所有值
lrange list 0 1        #得到1-2的值
rpush list right       #向list右端加值

lpop/rpop list         #移除list左边/右边的一个元素
lindex list            #通过下标获取值
llen   list            #list长度
lrem list 2 three       #移除2个three的值

ltrim list 1 2         #截取1-2的值,list只保存下表为1和2的值

rpoplpush list mylist  #从list右端取出一个值,放在mylist的左端

lset list 0 item        #将list左端第0个值设置为item,如果list为空,则设置失败

linsert list before “word” “other” #向list中值为word的左边插入other值

消息排队,消息队列

Set

set中的值不能重复

sadd myset “hello”     #向myset中添加元素

smembers myset         #获取myset值

sismember  myset hello            #查询是否hello

scard myset           #获取myset值的个数

srem myset hello        #移除myset中的 hello值

srandmember myset 2     #随机抽出2个myset中的元素

spop myset              #随机弹出一个myset的元素

smove myset myset2 “kuangshen” #将一个值从一个集合移动到另一个集合

- sdiff差集
- sinter交集
- sunion并集

微博,a用户将所有关注的人放在一个set集合中,将他们的粉丝也放在一个集合中

共同关注,共同爱好,二度好友,推荐好友

Hash

map集合 key-value键值对

和string对比
hset myhash field1 kuangshen
hget myhash field1
hmset myhash field1 kuangshen filed2 liu
hmget myhash field1 field2
hgetall myhash
hexists myhash field1
hlen myhash

hincrby myhash field3 1/-1  #将field3的值加一减一

hsetnx myset field4 hello      #如果field4存在则设置失败

hash变更数据,尤其是经常变动的信息,更适合于对象的存储,string更加适合字符串

Zset

在set的基础上添加了排序

zadd salary 2500 xiaohong
zadd salary 250 xiaogang
zadd salary 2600 xiaoming

zrangebyscore salary -inf +inf             #将薪水排序
zrevrange salary 0 -1                      #从大到小进行排序
zrangebyscore salary -inf +inf withscores   #将薪水排序(带上数字和值)

zrange salary 0 -1                    #读取所有信息
zrem Salary xiaohong                 #移除指定集合
zcard salary                          #显示几个元素

zcount salary 1 3                    #1-3之间有几个值

set排序 工资表排序,判断权重排序,排行榜应用

三种特殊数据类型

geospatial地理位置

朋友的定位,附近的人,打车距离

#定义城市的经度和纬度
geoadd china:city 106.50 29.53 chongqing 114.05 22.52 shenzhen


geopos china:city chongqing


geodist china:city chongqing shenzhen (km)  #查询两地距离,默认为m可以改为km

#附近的人
georadius china:city 110 30 500 km withdist #查询110 30附近500公里内的城市信息

#指定元素周围的其他元素
georadiusbymember china:city shanghai 400 km

#返回11个字符的geohash字符串
geohash china:city beijing chongqi

zrem china:city beijing  #移除指定元素

Hyperloglog

网页的UV(一个人访问一个网站多次,但是还是算作一个人),基数统计法,占用的内存小2^64的元素,只用12kb内存,有0.81%错误率

pfadd mykey a b c d e f g h
pfcount mykey
pfadd mykey2 i j k l m n o
pfmerge mykey3 mykey mykey2                     #将mykey和mykey2进行基数统计法
pfcount mykey3


Bitmaps

统计用户信息,活跃,不活跃!登录,未登录!打卡,365打卡!两个状态,都可以使用bitmaps

setbit sign 0 1
setbit sign 1 0
setbit sign 2 1
setbit sign 3 0
setbit sign 4 1

#查看某一天是否打卡
getbit sign 3
#统计打卡天数!
bitcount sign

事务

redis单条命令是保存原子性的,但是事务不保证原子性

redis事务本质:一组命令的集合!一个事务中的命令都会被序列化,在事务执行过程中,会按照顺序执行,一次性,顺序,排他性!执行一些列命令!

redis事务

  1. 开启事务

  2. 命令入队

  3. 执行事务

    multi          #开启事务
    set k1 v1
    set k2 v2
    get k2
    set k3 v3
    exec           #执行
    #结果
    ok
    ok
    “v2”
    ok
    
    
    discard        #取消事务   则入队命令都不会执行
    

    编译异常

    代码,命令有问题,事务中的所有都不会执行

    运行时异常

    某句命令错误,不影响其他命令的执行

    悲观锁
    • 很悲观,认为什么时候都会出现问题,无论做什么都会加锁

乐观锁
  • 很乐观,认为什么时候都不会出现问题,所以不会上锁!更新数据的时候,在此期间是否有人回判断一下再次期间别人有没有去更新这个数据,可以使用版本号等机制。
  • ```bash
    
    set money 100
    set out 0
    watch money
    multi
    decrby money 20
    incrby out 20
    exec
    #当在执行前money的值有改动则会执行失败
    
    

Jedis

java操作redis的中间件,官方推荐的方式

  1. 先导入对应的依赖

      <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>3.2.0</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.62</version>
            </dependency>
    
  2. 测试链接

package com.kuang;

import redis.clients.jedis.Jedis;

public class TestPing {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("127.0.0.1",6379);

        System.out.println( jedis.ping());
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Us5nkfzV-1591575392454)(C:\Users\刘方正\AppData\Roaming\Typora\typora-user-images\image-20200605114114974.png)]

springboot整合

在springboot2.0之后,原来使用的jedis被替换为了lettuce

jedis:采用的直连,多个线程操作的话,是不安全的,如果想要避免不安全的话,使用jedis pool更像BIO模式

lettuce:采用netty ,实例可以在多个线程中进行共享,不存在线程不安全。可以减少线程数据,更像NIO模式

源码分析:

@Bean
    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    )
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

测试一下

  1. 导入依赖
  2. 配置连接
  3. 测试

Redis.conf详解

bind127.0.0.1 #绑定的主机地址,不设置默认将处理所有请求

protected-modeyes # 3.2里的参数,是否开启保护模式,默认开启。要是配置里没有指定bind和密码。开启该参数后,redis只会本地进行访问,拒绝外部访问。要是开启了密码 和bind,可以开启。否 则最好关闭,设置为no

port6379 #指定redis监听端口

tcp-backlog511 #此参数确定了TCP连接中已完成队列(完成三次握手之后)的长度, 当然此值必须不大于Linux系统定义的/proc/sys/net/core/somaxconn值,默认是511,而Linux的默认参数值是128。当系统并发量大并且客户端速度缓慢的时候,可以将这二个参数一起参考设定。该内核参数默认值一般是128,对于负载很大的服务程序来说大大的不够。一般会将它修改为2048或者更大。在/etc/sysctl.conf中添加:net.core.somaxconn =2048,然后在终端中执行sysctl -p

timeout0 #当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能

tcp-keepalive300 #如果设置不为0,就使用配置tcp的SO_KEEPALIVE值,使用keepalive有两个好处:检测挂掉的对端。降低中间设备出问题而导致网络看似连接却已经与对端端口的问题。在Linux内核中,设置了keepalive,redis会定时给对端发送ack。检测到对端关闭需要两倍的设置值。

**daemonizeno **#当为yes的时候,以守护进程的模式运行(后台运行)

supervisedno可以通过upstart和systemd管理Redis守护进程,这个参数是和具体的操作系统相关的

pidfile/var/run/redis_6379.pid #当redis以守护进程方式运行时,默认写入pid的文件及路径

loglevelnotice 日志级别,要用warning

logfile"" #指定了记录日志的文件。空字符串的话,日志会打印到标准输出设备。后台运行的redis标准输出是/dev/null

databases16 数据库的数量,默认使用的数据库是DB 0。可以通过”SELECT “命令选择一个db

save900 1 #900秒有一个key变化,就做一个保存

save300 10 #300秒有10个key变化,就做一个保存,这里需要和开发沟通

save60 10000 #60秒有10000个key变化就做一个保存

stop-writes-on-bgsave-erroryes #在出现错误的时候,是不是要停止保存

rdbcompressionyes使用压缩rdb文件,rdb文件压缩使用LZF压缩算法,yes:压缩,但是需要一些cpu的消耗。no:不压缩,需要更多的磁盘空间

rdbchecksumyes是否校验rdb文件。从rdb格式的第五个版本开始,在rdb文件的末尾会带上CRC64的校验和。这跟有利于文件的容错性,但是在保存rdb文件的时候,会有大概10%的性能损耗,所以如果你追求高性能,可以关闭该配置。

dbfilenamedump.rdb rdb文件的名称

dir./ 数据目录,数据库的写入会在这个目录。rdb、aof文件也会写在这个目录

slave-serve-stale-datayes当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:1) 如果slave-serve-stale-data设置为yes(默认设置),从库会继续响应客户端的请求。2) 如果slave-serve-stale-data设置为no,除去INFO和SLAVOF命令之外的任何请求都会返回一个错误”SYNC with master in progress”

slave-read-onlyyes作为从服务器,默认情况下是只读的(yes),可以修改成NO,用于写(不建议)

repl-diskless-syncno是否使用socket方式复制数据。目前redis复制提供两种方式,disk和socket。如果新的slave连上来或者重连的slave无法部分同步,就会执行全量同步,master会生成rdb文件。有2种方式:disk方式是master创建一个新的进程把rdb文件保存到磁盘,再把磁盘上的rdb文件传递给slave。socket是master创建一个新的进程,直接把rdb文件以socket的方式发给slave。disk方式的时候,当一个rdb保存的过程中,多个slave都能共享这个rdb文件。socket的方式就的一个个slave顺序复制。在磁盘速度缓慢,网速快的情况下推荐用socket方式。

repl-diskless-sync-delay5 diskless复制的延迟时间,防止设置为0。一旦复制开始,节点不会再接收新slave的复制请求直到下一个rdb传输。所以最好等待一段时间,等更多的slave连上来。

repl-disable-tcp-nodelayno是否禁止复制tcp链接的tcp nodelay[gs1] [gs2] 参数,可传递yes或者no。默认是no,即使用tcp nodelay。如果master设置了yes来禁止tcp nodelay设置,在把数据复制给slave的时候,会减少包的数量和更小的网络带宽。但是这也可能带来数据的延迟。默认我们推荐更小的延迟,但是在数据量传输很大的场景下,建议选择yes。

slave-priority100当master不可用,Sentinel会根据slave的优先级选举一个master。最低的优先级的slave,当选master。而配置成0,永远不会被选举。

appendonlyno #默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。但是redis如果中途宕机,会导致可能有几分钟的数据丢失,根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性。Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件

appendfilename"appendonly.aof" sof文件名

appendfsynceverysec #aof持久化策略的配置

#no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快。

#always表示每次写入都执行fsync,以保证数据同步到磁盘。

#everysec表示每秒执行一次fsync,可能会导致丢失这1s数据。

no-appendfsync-on-rewriteno在aof重写或者写入rdb文件的时候,会执行大量IO,此时对于everysec和always的aof模式来说,执行fsync会造成阻塞过长时间,no-appendfsync-on-rewrite字段设置为默认设置为no。如果对延迟要求很高的应用,这个字段可以设置为yes,否则还是设置为no,这样对持久化特性来说这是更安全的选择。设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no,建议yes。Linux的默认fsync策略是30秒。可能丢失30秒数据。

auto-aof-rewrite-percentage100 aof自动重写配置。当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,即当aof文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写。当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过程。

auto-aof-rewrite-min-size64mb #设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写

aof-load-truncatedyes#aof文件可能在尾部是不完整的,当redis启动的时候,aof文件的数据被载入内存。重启可能发生在redis所在的主机操作系统宕机后,尤其在ext4文件系统没有加上data=ordered选项(redis宕机或者异常终止不会造成尾部不完整现象。)出现这种现象,可以选择让redis退出,或者导入尽可能多的数据。如果选择的是yes,当截断的aof文件被导入的时候,会自动发布一个log给客户端然后load。如果是no,用户必须手动redis-check-aof修复AOF文件才可以。

lua-time-limit5000如果达到最大时间限制(毫秒),redis会记个log,然后返回error。当一个脚本超过了最大时限。只有SCRIPT KILL和SHUTDOWN NOSAVE可以用。第一个可以杀没有调write命令的东西。要是已经调用了write,只能用第二个命令杀。

slowlog-log-slower-than10000 slog log是用来记录redis运行中执行比较慢的命令耗时。当命令的执行超过了指定时间,就记录在slow log中,slog log保存在内存中,所以没有IO操作。

#执行时间比slowlog-log-slower-than大的请求记录到slowlog里面,单位是微秒,所以1000000就是1秒。注意,负数时间会禁用慢查询日志,而0则会强制记录所有命令。

slowlog-max-len128慢查询日志长度。当一个新的命令被写进日志的时候,最老的那个记录会被删掉。这个长度没有限制。只要有足够的内存就行。你可以通过 SLOWLOG RESET 来释放内存。

latency-monitor-threshold0 #延迟监控功能是用来监控redis中执行比较缓慢的一些操作,用LATENCY打印redis实例在跑命令时的耗时图表。只记录大于等于下边设置的值的操作。0的话,就是关闭监视。默认延迟监控功能是关闭的,如果你需要打开,也可以通过CONFIGSET命令动态设置。

notify-keyspace-events""

#键空间通知使得客户端可以通过订阅频道或模式,来接收那些以某种方式改动了Redis 数据集的事件。因为开启键空间通知功能需要消耗一些 CPU ,所以在默认配置下,该功能处于关闭状态。

#notify-keyspace-events的参数可以是以下字符的任意组合,它指定了服务器该发送哪些类型的通知:

##K 键空间通知,所有通知以 keyspace@ 为前缀

##E 键事件通知,所有通知以 keyevent@ 为前缀

##g DEL 、 EXPIRE 、RENAME 等类型无关的通用命令的通知

##$ 字符串命令的通知

##l 列表命令的通知

##s 集合命令的通知

##h 哈希命令的通知

##z 有序集合命令的通知

##x 过期事件:每当有过期键被删除时发送

##e 驱逐(evict)事件:每当有键因为 maxmemory 政策而被删除时发送

##A 参数 g$lshzxe 的别名

#输入的参数中至少要有一个 K 或者 E,否则的话,不管其余的参数是什么,都不会有任何 通知被分发。详细使用可以参考http://redis.io/topics/notifications

hash-max-ziplist-entries512#数据量小于等于hash-max-ziplist-entries的用ziplist,大于hash-max-ziplist-entries用hash

**hash-max-ziplist-value64 **#value大小小于等于hash-max-ziplist-value的用ziplist,大于hash-max-ziplist-value用hash。

list-max-ziplist-size-2

list-compress-depth0

set-max-intset-entries512 #数据量小于等于set-max-intset-entries用iniset,大于set-max-intset-entries用set。

zset-max-ziplist-entries128 #数据量小于等于zset-max-ziplist-entries用ziplist,大于zset-max-ziplist-entries用zset。

zset-max-ziplist-value64 #value大小小于等于zset-max-ziplist-value用ziplist,大于zset-max-ziplist-value用zset。

hll-sparse-max-bytes3000#value大小小于等于hll-sparse-max-bytes使用稀疏数据结构(sparse),大于hll-sparse-max-bytes使用稠密的数据结构(dense)。一个比16000大的value是几乎没用的,建议的value大概为3000。如果对CPU要求不高,对空间要求较高的,建议设置到10000左右。

activerehashingyes#Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用。当你的使用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存。

client-output-buffer-limitnormal 0 0 0

##对客户端输出缓冲进行限制可以强迫那些不从服务器读取数据的客户端断开连接,用来强制关闭传输缓慢的客户端。

#对于normalclient,第一个0表示取消hard limit,第二个0和第三个0表示取消soft limit,normal client默认取消限制,因为如果没有寻问,他们是不会接收数据的。

client-output-buffer-limitslave 256mb 64mb 60 #对于slaveclient和MONITER client,如果client-output-buffer一旦超过256mb,又或者超过64mb持续60秒,那么服务器就会立即断开客户端连接。

**client-output-buffer-limitpubsub 32mb 8mb 60 **#对于pubsub client,如果client-output-buffer一旦超过32mb,又或者超过8mb持续60秒,那么服务器就会立即断开客户端连接。

hz10 #redis执行任务的频率为1s除以hz。

aof-rewrite-incremental-fsyncyes #在aof重写的时候,如果打开了aof-rewrite-incremental-fsync开关,系统会每32MB执行一次fsync。这对于把文件写入磁盘是有帮助的,可以避免过大的延迟峰值。
————————————————
版权声明:本文为CSDN博主「zwcwu31」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zwc2xm/article/details/78663075

Redis持久化

RDB

是内存数据库,如果不讲内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失。所以Redis提供了持久化的功能。

rdb保存的文件是dump.rdb

在redis.conf配置文件中200+多行

save 900 1

save 300 10

save 60 10000

即在900秒内修改一次,在300秒内修改10,在60秒内修改10000ci会自动生成dump.rdb文件

触发机制

  1. 满足save规则
  2. 执行flushall命令
  3. 退出redis

只需要将rdb文件放在redis启动目录下面,redis在启动的时候就会自动扫描

优点

  1. 适合大规模的数据恢复
  2. 对数据的完整性要求不高

缺点

  1. 需要一定的时间间隔进程操作!如果redis意外宕机了,最后一次修改的数据就没有了
  2. fork进程时,会占用一定的内容空间!
AOF(append only file)

将我们所有的写命令记录下来

aof保存的是appendonly.aof

配置文件

appendonly no                        #默认是不开启aof的,默认使用rdb,在大部分情况下,用rdb就够了
appendfilename “aooendonly.aof”                      # “持久化的文件名字”      
#appendfsync always                                 #每次都会修改sync,消耗性能
appendfsync everysec                                #每秒执行一次sync,可能会丢失1s的数据
#appendfsync no                                     #不执行sync 这个时候操作系统自己同步数据,速度最快

如果aof文件有错位等错误,可以使用redis-check-aof文件进行修复

优点

  1. 每一次修改都同步,文件的完整性比较好
  2. 每秒同步一次,可能会丢失一秒数据
  3. 从不同步,效率最高

缺点

  1. 相对于rdb文件来说,aof远远大于rdb,修复速度也远远大于。
  2. aof效率比较慢

Redis发布订阅

通信 队列 发送者====订阅者接受

订阅端
subscribe liufangzheng                      #订阅liufangzheng这个频道

发送端
publish liufangzheng “hello,liufangzheng”   #向订阅liufangzheng的人发送hello,liufangzheng信息


结果,订阅端显示
<1>"message"                      #消息
<2>"liufangzhegn"                 #频道
<3>"hello,liufangzheng"           #消息内容

img

使用场景

  1. 实时消息系统

  2. 实时聊天

  3. 订阅关注

    复杂的可以使用 消息中间件MQ

Redis主从复制

一、Master&Slave是什么?

     也就是我们所说的主从复制,主机数据更新后根据配置和策略,自动同步到备机

的master/slaver机制,Master以写为主,Slave以读为主。

二、它能干嘛?

   1、读写分离;

   2、容灾恢复。

三、怎么玩?

   1、配从(库)不配主(库);

   2、从库配置:slaveof [主库IP] [主库端口];

       补充:每次slave与master断开后,都需要重新连接,除非你配置进redis.conf文件;

                  键入info replication 可以查看redis主从信息。

   3、修改配置文件细节操作

         - 拷贝多个redis.conf文件

         - 指定端口

         - 开启daemonize yes

         - Pid文件名字

         - Log文件名字

         - Dump.rdb名字

    4、常用3招

          - 一主二仆

              一个Master,两个Slave,Slave只能读不能写;当Slave与Master断开后需要重新slave of连接才可建立之

       前的主从关系;Master挂掉后,Master关系依然存在,Master重启即可恢复。

       - 薪火相传





             上一个Slave可以是下一个Slave的Master,Slave同样可以接收其他slaves的连接和同步请求,那么该slave作为了

       链条中下一个slave的Master,如此可以有效减轻Master的写压力。如果slave中途变更转向,会清除之前的数据,重新

       建立最新的。

       - 反客为主

                   当Master挂掉后,Slave可键入命令 slaveof no one使当前redis停止与其他Master redis数据同步,转成

          Master redis。

四、复制原理

   1、Slave启动成功连接到master后会发送一个sync命令;

   2、Master接到命令启动后的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master

        将传送整个数据文件到slave,以完成一次完全同步;

   3、全量复制:而slave服务在数据库文件数据后,将其存盘并加载到内存中;

   4、增量复制:Master继续将新的所有收集到的修改命令依次传给slave,完成同步;

   5、但是只要是重新连接master,一次完全同步(全量复制)将被自动执行。

五、哨兵模式(sentinel)

   反客为主的自动版,能够后台监控Master库是否故障,如果故障了根据投票数自动将slave库转换为主库。一组sentinel能

   同时监控多个Master。

   使用步骤:

   1、在Master对应redis.conf同目录下新建sentinel.conf文件,名字绝对不能错;

   2、配置哨兵,在sentinel.conf文件中填入内容:

         sentinel monitor 被监控数据库名字(自己起名字) ip port 1

         说明:上面最后一个数字1,表示主机挂掉后slave投票看让谁接替成为主机,得票数多少后成为主机。

  3、启动哨兵模式:

        命令键入:redis-sentinel  /myredis/sentinel.conf

       注:上述sentinel.conf路径按各自实际情况配置

六、复制的缺点

        延时,由于所有的写操作都是在Master上操作,然后同步更新到Slave上,所以从Master同步到Slave机器有一定

   的延迟,当系统很繁忙的时候,延迟问题会更加严重,Slave机器数量的增加也会使得这个问题更加严重。

————————————————
版权声明:本文为CSDN博主「遛狗大师」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zhangguanghui002/article/details/78524533

Redis缓存穿透和雪崩

一、缓存穿透

1、概念

缓存穿透的概念很简单,用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。

这里需要注意和缓存击穿的区别,缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

为了避免缓存穿透其实有很多种解决方案。下面介绍几种。

2、解决方案

(1)布隆过滤器

布隆过滤器是一种数据结构,垃圾网站和正常网站加起来全世界据统计也有几十亿个。网警要过滤这些垃圾网站,总不能到数据库里面一个一个去比较吧,这就可以使用布隆过滤器。假设我们存储一亿个垃圾网站地址。

可以先有一亿个二进制比特,然后网警用八个不同的随机数产生器(F1,F2, …,F8) 产生八个信息指纹(f1, f2, …, f8)。接下来用一个随机数产生器 G 把这八个信息指纹映射到 1 到1亿中的八个自然数 g1, g2, …,g8。最后把这八个位置的二进制全部设置为一。过程如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CSq5OSs5-1591575392457)(https://pics6.baidu.com/feed/21a4462309f79052696269b62519dfcc7acbd52d.jpeg?token=77d2a5fe27c3fd42d7ae7a07d68fadec&s=7DA434729B0A4D495EE195DF000050B3)]

有一天网警查到了一个可疑的网站,想判断一下是否是XX网站,首先将可疑网站通过哈希映射到1亿个比特数组上的8个点。如果8个点的其中有一个点不为1,则可以判断该元素一定不存在集合中。

那这个布隆过滤器是如何解决redis中的缓存穿透呢?很简单首先也是对所有可能查询的参数以hash形式存储,当用户想要查询的时候,使用布隆过滤器发现不在集合中,就直接丢弃,不再对持久层查询。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TffDaSmR-1591575392459)(https://pics6.baidu.com/feed/d788d43f8794a4c2773846a5251e13d3ac6e3910.jpeg?token=029a90d30125df6852018a7e4e7294ff&s=1AA27423D99E44C80E5CE5DE000080B1)]

这个形式很简单。

2、缓存空对象

当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KU3DZc95-1591575392460)(https://pics6.baidu.com/feed/203fb80e7bec54e7a4ba970397d293564ec26a4d.jpeg?token=0068420533f90cb97750b10ce30053b8&s=9A027C239B9E4DC848DDC4D6000080B2)]

但是这种方法会存在两个问题:

如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。二、缓存雪崩

1、概念

缓存雪崩是指,缓存层出现了错误,不能正常工作了。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lBJGG7ES-1591575392461)(https://pics3.baidu.com/feed/9c16fdfaaf51f3dec6606ae3a504f81938297953.jpeg?token=3f9f811a459ba91f1295f1fbaccf5cb7&s=BEAA742387E7490B0A5974C8000030B0)]

2、解决方案

(1)redis高可用

这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群。

(2)限流降级

这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

(3)数据预热

数产生器(F1,F2, …,F8) 产生八个信息指纹(f1, f2, …, f8)。接下来用一个随机数产生器 G 把这八个信息指纹映射到 1 到1亿中的八个自然数 g1, g2, …,g8。最后把这八个位置的二进制全部设置为一。过程如下:

[外链图片转存中…(img-CSq5OSs5-1591575392457)]

有一天网警查到了一个可疑的网站,想判断一下是否是XX网站,首先将可疑网站通过哈希映射到1亿个比特数组上的8个点。如果8个点的其中有一个点不为1,则可以判断该元素一定不存在集合中。

那这个布隆过滤器是如何解决redis中的缓存穿透呢?很简单首先也是对所有可能查询的参数以hash形式存储,当用户想要查询的时候,使用布隆过滤器发现不在集合中,就直接丢弃,不再对持久层查询。

[外链图片转存中…(img-TffDaSmR-1591575392459)]

这个形式很简单。

2、缓存空对象

当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源;

[外链图片转存中…(img-KU3DZc95-1591575392460)]

但是这种方法会存在两个问题:

如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。二、缓存雪崩

1、概念

缓存雪崩是指,缓存层出现了错误,不能正常工作了。于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。

[外链图片转存中…(img-lBJGG7ES-1591575392461)]

2、解决方案

(1)redis高可用

这个思想的含义是,既然redis有可能挂掉,那我多增设几台redis,这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群。

(2)限流降级

这个解决方案的思想是,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

(3)数据预热

数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值