Redis学习历程学习笔记

记录一份

REDIS
一、什么是redis?
是一个完全开源免费、遵守BSD协议、高性能的NOSQL的Key-Value形式的数据库。

二、特点
(1)基于内存
(2)支持持久化
(3)单个Key可存入512M
(4)支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
(5)支持多种数据类型
(6)支持集群(0 - 1516个库
(7)支持消息队列

三、安装(基于Linux)
Step1: yum -y install gcc automake autoconf libtool make
Step2: wget 地址 -P 路径
       wget http://download.redis.io/releases/redis-5.0.7.tar.gz
Step3: 解压
Step4: 进入解压后的目录,执行make MALLOC=libc
Step5: make PREFIX=/usr/local/redis install   (PREFIX没有--)

四、启动
启动服务端:./redis-server [配置文件] [--port xxx] [--slaveof ip port]
启动客户端:./redis-cli  -h <IP地址>
                        -p <端口>(默认端口为6379-a <密码>
                        --no-auth-warning   # 在命令行输入密码的时候,不显示警告
                        --raw  避免中文乱码
                        -c 连接集群
                        -n <db_number>
检测服务端是否启动:
在客户端下执行:ping即可,出现PONG字样即成功

redis-server --version   查看版本信息
redis-server --help      帮助信息

五、配置文件
默认的配置文件在解压目录下,redis.conf

# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes

# units are case insensitive so 1GB 1Gb 1gB are all the same.

# bind 绑定主机地址,意思是允许来自哪个网卡的redis请求
bind 192.168.1.102 127.0.0.1
bind 0.0.0.0

# daemonize 守护进程,yes表示以守护进程方式启动
daemonize yes | no

# pidfile 当redis以守护进程启动时,将pid写入一个文件
pidfile /var/run/redis_6379.pid

# protected-mode
protected-mode yes

# port 监听端口
port 6379

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

# loglevel  日志记录级别(debug, verbose, notice, warning)
loglevel verbose

# logfile  日志记录方式,默认标准输出。如果redis以守护进程方式启动,而这里又配置了stdout,则redis将日志输出到/dev/null
logfile stdout

# databases  数据库数量,默认16个,dbid范围0 - 15
databases 16

# save 指定在多少秒内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合使用
#   满足以下条件将会同步数据:
#   900秒(15分钟)内有1个更改
#   300秒(5分钟)内有10个更改
#   60秒内有10000个更改
#   Note: 可以把所有“save”行注释掉,这样就取消同步操作了
save 900 1
save 300 10
save 60  10000

# rdbcompression yes表示压缩,采用LZF压缩方式。为了节省CPU时间,可以关闭,但会导致数据文件巨大
rdbcompression yes | no

# dbfilename  数据库文件名
dbfilename dump.db

# dir  指定数据库文件存放目录
dir ./

# slaveof  设置本机为slave后,在redis启动时,它会自动从master进行数据同步
slaveof <masterip> <masterport>

# masterauth  当master服务设置了密码保护时,slave服务连接master的密码
masterauth <master-password>

# requirepass  设置redis连接密码。redis 3.0以后必须设置。如果设置了连接时通过:1)redis-cli -a 密码
(2)连接进去后,通过auth 密码 验证
requirepass foobared

# maxclients  设置同一时间最大客户端连接数,默认无限制(也就是注释状态,或者设置为0)
如果到达限制,redis会关闭新的连接并向客户端返回max number of clients reached信息
maxclients 0

# maxmemory  指定最大内存,redis启动时会加载数据文件到内存。到达最大后,redis会尝试清除已到期或即将到期的key
当此方法处理后,仍到达最大,将无法再进行写入操作,但仍可以读取。redis的新VM机制,会把key存入内存,value存入swap
maxmeory <bytes>

# LRU means Least Recently Used
# LFU means Least Frequently Used

# volatile-lru -> Evict using approximated LRU among the keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key among the ones with an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.

# maxmemory-policy noeviction

# appendonly  是否在每次更新操作之后进行日志记录
appendonly no 

# appendfilename  指定更新日志文件名
appendfilename appendonly.aof

# appendfsync  指定日志更新条件
# no:表示等操作系统进行数据缓存同步到磁盘(快,完全依赖OS,性能最好,持久化没保证)
# always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
# everysec:表示每秒同步一次(折衷,默认值)
appendfsync everysec

# vm-enabled  指定是否启用虚拟内存机制,默认no
# VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中
# 把vm-enabled设置为yes,根据需要设置好接下来的三个VM参数,就可以启动VM了
vm-enabled no | yes

# vm-swap-file  redis交换文件最好的存储是SSD
虚拟内存文件路径,不可多个redis实例共享
vm-swap-file /tmp/redis.swap

# vm-max-memory  将所有大于vm-max-memory的数据存入虚拟内存,
无论vm-max-memory设置多少,所有索引数据都是内存存储的
(redis的索引数据就是keys)
vm-max-memory 0

# Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,
# 但一个page上不能被多个对象共享,vm-page-size是要根据存储的数据大小来设定的。
# 建议如果存储很多小对象,page大小最后设置为32或64bytes;
如果存储很大的对象,则可以使用更大的page,如果不确定,就使用默认值
vm-page-size 32

# vm-pages 
# 设置swap文件中的page数量由于页表(一种表示页面空闲或使用的bitmap)是存放在内存中的,在磁盘上每8个pages将消耗1byte的内存
# swap空间总容量为 vm-page-size * vm-pages
vm-pages 134217728

# vm-max-threads  
# 设置访问swap文件的I/O线程数,最后不要超过机器的核数,
# 如果设置为0,那么所有对swap文件的操作都是串行的,
# 可能会造成比较长时间的延迟,默认值为4 
vm-max-threads 4

# 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
hash-max-zipmap-entries 512
hash-max-zipmap-value 64

list-max-ziplist-entries 512
list-max-ziplist-value 64

set-max-intset-entries 512

zset-max-ziplist-entries 128
zset-max-ziplist-value 64

# 指定是否激活重置哈希,默认为开启
activerehashing yes

################################## INCLUDES ###################################

# 指定包含其他的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各实例又拥有自己的特定配置文件
# include /path/to/local.conf
# include /path/to/other.conf

六、关闭服务
Step1: 连接到redis后
Step2: shutdown [save | nosave] 默认将内存中的数据保存到数据文件中

七、Redis命名规范
1. 单个Key可存入512MB
2. key名字不超过1024B
3. 不要太短,降低可读性
4. 区分大小写
5. 使用:分隔(行业规定),例如:username:id:1

八、数据类型
nil
string
hash
list
set
sorted set
bitmap
HyperLogLog

################################## Redis命令 ###################################、
(一)公共命令
auth password           验证密码

ping  [message]         测试服务器是否运行

echo message            输出一个message

time

lastsave

clear                   清屏

quit                    关闭当前连接

shutdown [save | nosave] 关闭服务,默认将内存中的数据保存到数据文件中

save                    同步保存数据

bgsave                  异步保存数据

sync                    主从同步

config get cfname cfval 获取配置信息
    1) "daemonize"
    2) "yes"

config set cfname cfval 设置配置信息

dbsize                  查看当前数据库有多少key,包括过期的

keys * | ?  | []        查看keys* | ?是通配符,*表示任意个任意字符,?表示一个任意的字符)
						有效的
                        
randomkey               随机地从当前数据库返回一个key,没有,返回nil
                        
move key dbid           把当前库中的key移动到指定的数据库,返回1,如果key在数据库存在,返回0,并且不移动;

select dbid             切换数据库

flushdb [async]         删除当前数据库所有的key,选项async表示异步执行删除操作(也就是在后台执行)

flushall [async]        删除所有数据库中的所有key,选项async表示异步执行删除操作(也就是在后台执行)

dump key                序列化key

type key                检测key的数据类型

rename key newkey       给key改名,如果newkey存在,则直接覆盖

renamenx key newkey     当key不存在时改名,并且返回1,否则返回0,不改名

del key [key ...]       删除存在的key,并返回成功删除个数

exists key [key ...]    检查key是否存在,并返回存在的key的个数

expire key seconds      给key设置过期时间(秒),默认永久(-1)
                        成功返回1,当key不存在或者不能设置时,返回0
                        
pexpire key miliseconds 给key设置过期时间(毫秒)

expireat key seconds    接受Unix时间戳

pexpireat key miliseconds 

ttl key                 查看key的剩余时间(秒)(time to live)(-2 无效)
                        当key不存在或者过期,返回-2
                        
pttl key                查看key的剩余时间(毫秒)

persist key             移除key的过期时间
                        当过期时间移除成功时,返回 1 。
                        如果 key 不存在或 key 没有设置过期时间,返回 0 。
pfadd key elm [elm ...] 添加一个或多个基数,有一个被添加就返回1,没有就返回0,不重复

pfcount key [key ...]   返回key中基数的个数,如果是多个key,则累加返回

pfmerge deskey skey [...] 合并,成功返回OK

(二)string
    string是二进制安全的,可以包含任何数据,例如,图片等
    
    二进制安全:在传输数据时,保证二进制数据的安全。也就是不会被篡改、破译等,
                如果被攻击,能及时检测出来。
                
                特点:
                    1. 编解码发生在客户端,执行效率高
                    2. 不需要频繁的编解码,不会发生乱码

    set key value  [EX seconds | PX miliseconds] [NX | XX]    设置key-value,如果key存在,就覆写
                                    EX,过期时间(秒)

                                    PX,过期时间(毫秒)
                                    NX,只有name不存在时,当前set操作才执行
                                    XX,只有name存在时,当前set操作才执行

    setnx key valuekey不存在时,就设置key-value,返回1;如果存在,返回0
    setex key seconds value         为指定的 key 设置值及其过期时间 如果 key 已经存在, SETEX 命令将会替换旧的值
    psetex key miliseconds value
    mset key value [key value ...]  一次性设置多个key-value键值对
    msetnx key value [key value ...] 当所有 key 都成功设置,返回 1
                                     如果所有给定 key 都设置失败(至少有一个 key 已经存在),那么返回 0
    setrange key offset value       用指定的字符串覆盖给定 key 所储存的字符串值,覆盖的位置从偏移量 offset 开始,返回字符串字节总长度
    append key valuevalue追加到key原有的值后面,并且返回追加后的长度;如果key不存在,就赋值并且返回字符串字节总长度

    get key                         获取keyvalue,如果key不存在,返回nil,如果存在但类型不是string,报错
    mget key [key ...]              一次性获取多个keyvalue,如果key不存在,当前key返回nil
    getrange key start end          获取keyvalue一部分[start, end]startend都支持负索引(都取得到)startend如果超过了原有string的长度,没有关系,会尽最大能力获取
                                    例如:getrange strin2 0 -1       getrange -3 -1
    getbit key offset               获取keyvalue在偏移量上的位值
    getset key value                先获取,再赋值
    
    strlen key                      获取keyvalue的字节长度,不存在返回0,存在但类型不是string,报错
    incr keykeyvalue自增1value必须为整型,否则报错),并且返回
                                    如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作
    decr keykeyvalue自减1value必须为整型),并且返回
    incrby key increment            让keyvalue自增increment指定的整型值(value必须为整型,可以为负整数),并且返回
    decrby key increment            让keyvalue自减increment指定的整型值(value必须为整型),并且返回
    incrbyfloat key increment       让keyvalue自增increment指定的浮点型 | 整型值,并且返回
    
(三)hash
    每个hash可以存2^32 - 1键值对(40多亿)
    如果把key中所有的键值对删除了,那么该key也就被回收了

    hset key field value [field value ...]  在指定的key中设置field-value(相当于Python中key = {field: value}
                                            返回设置的个数;如果是覆写返回0;如果既有覆写也有设置,返回设置的个数        
    hsetnx key feild value
    hmset key field value [field value ...] 一次性在key中设置多个field-value键值对,永远返回True

    hget key field                          在指定的key中获取field的value;不存在,返回nil
    hmget key field [field ...]             一次性在key中获取多个field的value
    hgetall key                             获取key中所有的field和value
    hkeys key                               获取key中所有的field
    hvals key                               获取key中所有的value
    hlen key                                统计key中有多少个键值对
    hstrlen key field                       返回哈希表中给定域相关联的值的字符串长度
                                            如果key or filed不存在返回0
    hdel key field [field ...]              删除key中的field键值对(如果把key中所有的键值对删除了,那么key也就被回收了)
    hexists key field                       检查key中是否存在field,key or field不存在返回0
    hincrby key field increment             让key中field的value自增increment指定的整型值(value必须为整型),并且返回
                                            如果哈希表的不存在
                                            一个新的哈希表被创建并执行 HINCRBY 命令
                                            如果指定的键(key)不存在
                                            那么在执行命令前,字段的值先被初始化为0
    hincrbyfloat key field increment        让key中field的value自增increment指定的浮点型 | 整型值 ,并且返回 

(四)list
    每个list最多可包含2^32 - 1个元素
    如果list没有元素了,则该key被删除

    lpush key value [value ...]key的左侧添加一个或多个value,返回添加后的长度
    lpushx key value [value ...]            往已存在的key的左侧添加一个value,返回添加后的长度,否则返回0
    rpush key value [value ...]key的右侧添加一个或多个value,返回添加后的长度
    rpushx key value [value ...]            往已存在的key的右侧添加一个或读个value,返回添加后的长度,否则返回0
    lrange key start end                    按照startend指定的范围查看keyvalue
    lindex key index                        查看keyindex(可以使用负索引)的value,超过范围,返回nil
    llen key                                查看key的长度,不存在,返回0,若存在但不是list,报错
    lpop keykey的左侧移除并且返回一个元素,如果列表为空或者不存在,返回nil
    rpop keykey的右侧移除并且返回一个元素,如果列表为空,返回nil
    blpop key [key ...] timeout             按照key的顺序,谁有值就从其左侧移除并且返回一个值;
                                            如果都没有值,则阻塞指定的timeout时间,返回nil
                                            或者直到发现key中有可弹出的元素为止。
                                            返回的结果:
                                            1)哪个key弹出的
                                            2)弹出的值
    brpop key [key ...] timeout             按照key的顺序,谁有值就从其右侧移除并且返回一个值;
                                            如果都没有值,则阻塞指定的timeout时间,返回nil
                                            或者直到发现key中有可弹出的元素为止。
                                            返回的结果:
                                            1)哪个key弹出的
                                            2)弹出的值
    lrem key count value                    根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素。
                                            count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。
                                            count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。
                                            count = 0 : 移除表中所有与 VALUE 相等的值。
                                            返回被移除元素的数量。 列表不存在时返回 0 。
                                            
    ltrim key start stop                    按照startend指定的范围保留key中的value,其余的都舍弃
    lset key index valuekey中的index位置上的值改为value,如果key不存在,则报错
    linsert key before | after v1 value2    往key中的v1之前 | 之后插入value2,返回插入后的长度,如果v1不存在,返回-1key不存在返回或者为空列表,返回0
    rpoplpush source destination            将source右侧最后一个元素移除并且返回,然后插入到destination的左侧
    brpoplpush source destination timeout   从source右侧弹出一个值,将弹出的值插入到destination左侧并且返回,
                                            如果source没有元素,则会阻塞列表直到超时或发现可弹出元素为止。
    
(五)set
    集合,无序,唯一,可包含2^32 - 1个成员
    
    sadd key member [member ...]key中添加一个或多个成员,返回添加的成员个数
    scard key                               统计key中的成员个数
    smembers key                            返回key中所有的成员
    sismember key member                    判断member是否是key的成员,是,返回1,否,返回0
    srandmember key [count]                 随机地从key中返回值,默认返回1个,如果key为空,返回nil,如果count超过总大小,没有关系,尽最大能力返回
                                            count 可以为负数,但可能有重复,正数,都是不同的
    srem key member [member ...]key中删除一个或多个成员,返回成功删除的个数
    spop key [count]key中随机删除count指定的成员并且返回,默认1个,如果key为空,返回nil,如果count超过总大小,没有关系,尽最大能力删除

    smove source destination member         把member从source移动到destination,移动成功(只要member在source存在即可,重不重复无所谓),返回1,失败(member在source中不存在),返回0
                                            当 destination 集合已经包含 member 元素时, SMOVE 命令只是简单地将 source 集合中的 member 元素删除。
    集合运算:
    差集:
        sdiff key1 [key2 ...]                key1与key2...等等做差集,去掉key1中在其他集合中存在的成员,剩下的成员返回
        sdiffstore destination key [key ...] 将差集的结果存储到destination中,返回存储之后的个数
    交集:
        sinter key1 [key2 ...]               将共同的成员返回
        sinterstore destination key [key ...]将共同的成员存储到destination中,返回存储之后的个数
    并集:
        sunion key1 [key2 ...]               将多个集合的成员合并
        sunionstore destination key [key ...]将合并的成员存储到destination中,返回存储之后的个数

(六)sorted set
    有序集合,有序,成员唯一,分数(浮点型)可以重复,可包含2^32 - 1个成员
    
    zadd key score member [score member ...]key添加一个或多个带分数的成员,返回添加的成员个数;如果是更新分数的话,返回0,因为不是添加
# ================================================================================================================
    zadd key score member [score member ...]

      有关zadd命令有两点需要注意:  Redis 3.2为zadd命令添加了nx、xx、ch、incr四个选项:

        nx:member必须不存在,才可以设置成功,用于添加.

        xx:member必须存在,才可以设置成功,用于添加.

        ch:返回此次操作后,有序结合元素和分数发生变化的个数.(默认不会对更新分数进行统计)

        incr: 对score进行添加操作,相当于后面介绍的zincrby. (在原有分数上增加)

      有序集合相比集合提供了排序字段,但是也产生了代价,zadd的时间复杂度是O(log(n)),sadd的时间复杂度为O(1).
# ================================================================== ============================================

    zcard key                                统计key中的成员个数
    zrange key start stop [withscores]       按照start和stop指定的范围获取key中的成员,选项withscores表示分数值也显示(可以使用负索引)
    zrevrange key start stop [withscores]    在zrange的基础上,反序输出
    zrangebyscore key min max [withscores] [LIMIT <offset> <count>]
    zrevrangebyscore key max min [withscores] [LIMIT <offset> <count>]  注意max要反过来
                                             min 和 max 可以是 -inf 和 +inf,这样一来,你就可以在不知道有序集的最低和最高 score 值的情况下,使用 ZRANGEBYSCORE 这类命令。
                                            ZRANGEBYSCORE zset (1 5
                                            返回所有符合条件 1 < score <= 5 的成员,而

                                            ZRANGEBYSCORE zset (5 (10
                                            则返回所有符合条件 5 < score < 10 的成员。
    zrangebylex key min max [LIMIT <offset> <count>]

    zcount key min max                       统计key中成员分数在min - max中的个数
    zlexcount key min max                    命令计算有序集合中指定字典区间内成员数量
                                            [ 符号
                                            [min 表示返回的结果中包含 min 值
                                            [max 表示返回的结果中包含 max 值
                                            ( 符号
                                            (min 表示返回的结果中不包含 min 值
                                            (max 表示返回的结果中不包含 max 值
                                            [MIN,[MAX 可以用 -,+ 代替

                                            - 表示得分最小值的成员
                                            + 表示得分最大值的成员
    zrank key member                         返回member在key中排名,按照分数从低到高排序,第一名为0,第二名为1,以此类推。key or member不存在,返回nil,相同的话,按照value的字典顺序排
    zrevrank key start stop                  分数从高到低排序
    zscore key member
    zrem key member [member ...]key中删除一个或多个成员,返回成功删除的个数
    zremrangebyrank key start stop           根据rank删除在startend指定的范围内的成员,返回成功删除的个数
    zremrangebyscore key min max             根据score删除在min和max指定的范围内的成员,返回成功删除的个数
    zincrby key increment member            # 在原有值基础上增加 increment,返回增加之后的值
                                            # 1. increment 可以为整型和浮点型
                                            # 2. increment 可以为负数

(七)bitmap(位图)
    Redis Bitmap 通过类似 map 结构存放 01 ( bit) 作为值
    Redis Bitmap 可以用来统计状态,如 日活,是否浏览过某个东西   
    
    setbit key offset value                  Redis setbit 命令用于设置或者清除一个 bitoffset必须为整型,value必须为0 or 1
               每次返回上次的value(一开始返回0)

(七)发布订阅
    Redis发布与订阅(pub/sub)是一种消息通信模式。
    
    发送者(pub),发送消息;
    订阅者(sub),接收消息;
    
    Redis客户端可以订阅任意数量的频道;
    
    subscribe channel [channel ...]             订阅一个或多个频道
                                                返回值:
                                                1)subscribe
                                                2)频道名
                                                3)序号(从1开始)
    psubscribe pattern [pattern ...]            根据模式来订阅一个或多个频道
                                                返回值:
                                                1)subscribe
                                                2)频道模式
                                                3)序号(从1开始)
    模式以*作为匹配符

    publish channel message                     向指定的channel发送message,发送成功即有响应的订阅者接受返回1,反之,返回0
    unsubscribe [channel [channel ...]]         取消订阅频道
    punsubscribe [channel [channel ...]]        根据模式取消订阅频道
    pubsub <subcommand> [argument [argument ...]查看发布者和订阅者状态
                                                subcommand:
                                                channels [pattern ...] 根据模式,如果有,查看相应的频道
                                                numpat                 返回用psubscribe订阅的频道个数,其余方式订阅的统统返回0
                                                numsub [channel ...]   判断用subscribe订阅的频道是否存在
                                                
(八)事务
    Redis中的事务一次可以执行多个命令,并且有以下三个重要保证:
    1)批量操作在发送exec命令前被放入队列缓存;
    2)收到exec命令后进入事务执行,事务中任意命令执行失败,其余命令依然被执行
    3)在事务执行过程中,其他客户端提交的命令请求不会插入到事务执行命令序列中
    
    一个事务从开始到执行会经历以下三个阶段:
    1)开始事务
    2)命令入队
    3)执行事务
    
    单个Redis命令的执行是原子性的,但Redis并没有在事务上增加任何维持原子的机制,所以Redis事务的执行并不是原子性的。
    事务可以理解为一个打包的批量执行脚本,但批量指令并非原子化的操作,中间某条指令的失败不会导致前面已做指令的回滚,
    也不会造成后续指令的不做。
    
    意思就是:事务中,如果是逻辑错误,是不会回滚的;但如果是语法错误,就会回滚。
    
    事务框架:
    
    watch key [key ...]         watch命令用于监视一个或多个key,如果在事务执行之前这个(或这些)key被其他命令所改动,那么事务将被打断执行
                                总是返回OK
    multi                       multi命令用于标记一个事务块的开始
                                总是返回OK
    多条命令入队                返回QUEUED,提示已入队缓存
    
    ....
    
    exec                        exec命令用于执行所有事务块内的命令
                                返回事务块内所有命令的返回值,
                                当操作被打断时,返回nil
    discard                     discard命令用于取消事务,放弃执行事务块内的所有命令
                                总是返回OK
                                
                                一个事务要么执行,要么不执行,所以execdiscard在一次事务中只能出现一个
    unwatch                     unwatch命令用于取消watch命令对所有key的监视
                                总是返回OK
                                
                                unwatch只能在execdiscard之前出现
                                
(九)数据淘汰机制
    为了防止内存溢出,可采取以下方法:
    
    在redis中,允许用户设置最大使用内存大小
    单台redis服务器,最大内存使用不应超过20G(建议)
            maxmemory 512G
            
    方法一:给key设置过期时间
    
    方法二:给maxmemory-policy设置相应的数据淘汰策略
    
    # LRU means Least Recently Used
        LRU意思是:最近最少使用。判断最近被使用的时间,目前最远的数据优先被淘汰
    # LFU means Least Frequently Used
        LFU意思是:最不经常使用。在一段时间内,数据被使用次数最少的,优先被淘汰
    
    # volatile-lru -> Evict using approximated LRU among the keys with an expire set.
                    从已设置过期时间的数据集中挑选最近最少使用的数据淘汰    
    # volatile-lfu -> Evict using approximated LFU among the keys with an expire set.
                    从已设置过期时间的数据集中,删除一段时间内使用次数最少的数据
    # volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
                    从已设置过期时间的数据集中挑选最近将要过期的数据淘汰
    # volatile-random -> Remove a random key among the ones with an expire set.
                    从已设置过期时间的数据集中,随机挑选数据淘汰
    # allkeys-lru -> Evict any key using approximated LRU. ----------------------》 广泛采用的策略
                    从数据集中挑选最近最少使用的数据淘汰
    # allkeys-lfu -> Evict any key using approximated LFU.
                    从数据集中,删除一段时间内使用次数最少的数据
    # allkeys-random -> Remove a random key, any key.
                    从数据集中随机挑选数据淘汰
    # noeviction -> Don't evict anything, just return an error on write operations.
                    禁止淘汰任何数据(默认配置),对于写操作,返回错误信息
    
(十)持久化
    
    方式一:RDB
    默认dump.rdb,是一种快照,保存一种状态
    
    优点:
        保存数据极快,还原极快
        适用于灾难备份
        
    缺点:
        小内存机器不适用
        RDB机制符合要求就会照快照
            条件:
                1. 服务器正常关闭
                2. save条件
    
    方式二:AOF
    如果要求不能丢失任何修改,可以采用AOF机制
    
    # appendfsync  指定日志更新条件
    # no:表示等操作系统进行数据缓存同步到磁盘(快,完全依赖OS,性能最好,持久化没保证)
    # always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
    # everysec:表示每秒同步一次(折衷,默认值)
    appendfsync everysec
    
(十一)Redis与数据库一致性

    方式一:实时同步
        适用于对强一致性要求高的情况下。
        即首先查询缓存,查询不到再从数据库查询并且保存到缓存;更新时,首先更新数据库,将缓存的设置过期
        (建议不要更新缓存,或者清空
        
            因为会导致“缓存穿透”:
                key对应的数据在数据源并不存在,查询一个一定不存在的数据时,由于缓存是在不命中时需要从数据库查询,
                数据库查询不到就不会写到缓存,这将导致不存在的数据每次请求都要到数据库去查询,
                造成缓存穿透。

            解决方案:
                数据库查询不到,就给Redis缓存一个空值,
                再次查询时,先到缓存中判断这个key存不存在,如果不存在,就往数据库查询;
                如果存在,再判断该keyvalue是否为空,如果是,就返回空,如果不是,就返回结果集。

            “缓存雪崩”:
                缓存中的内容集中在一段时间失效,造成大量缓存穿透,所有的请求压力都落在底层数据库上。
            
            解决方案:
                可以分析用户行为,让缓存失效时间均匀分布;
                再缓存失效时,可以考虑加锁或者队列来控制读数据库写缓存的线程数量,
                这样就避免失效时大量并发都落在底层数据库上。


            “缓存击穿”
                key对应的数据存在,但在redis中过期,此时若有大量并发请求过来
                ,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,
                这个时候大并发的请求可能会瞬间把后端DB压垮。
            解决方案:
                利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试。
        )
        
    方式二:异步队列
        适用于对并发程度要求高的情况下,使用kafka等消息中间件来处理
        
    方式三:阿里的同步工具Canal
        模拟MySQL的Master和Slave同步机制,监控数据库的binary log的日志更新记录来更新缓存
        
    方式四:Redis脚本
        编写Redis脚本,使用Lua解释器执行
        
    方式五:UDF自定义函数
        面对MySQL的API编程,使用触发器来进行缓存更新
        
    方式六:任务计划
    
(十二)提升并发性能
    
    (1)垂直扩展:提升单机处理能力
        1. 增强单机硬件性能(如果钱不是问题,就可以考虑这个,毕竟商业“时间就是金钱”)
        2. 提升单机架构性能
    
    (2)水平扩展:增加服务器数量

# ============================

恢复数据:
恢复数据,只需将备份文件 ( dump.rdb ) 移动到 Redis 安装目录并启动服务即可

# ============================

(十三)主从同步
    主Master:写
    从Slaves:读
    
    一个主可以有多个从;
    一个从只能隶属于一个主
    为了主从复制的速度和连接的稳定性,Slave和Master最好在同一个局域网内

    部署流程:
        主Redis无需配置,从Redis需要做以下配置:
        Step1: port 6378    (说明:如果是真实的Redis服务器,无需改端口号;因为是虚拟测试,就改端口,来模拟不同的主机服务器)
        Step2: slaveof <masterip> <masterport>
               slaveof 192.168.1.102 6379
               masterauth hardy9sap
        step3:从服务端启动
               redis-server ./redis.conf --port 6378 --slaveof 192.168.1.102 6379
               
               登录从客户端
               redis-cli -p 6378 -a hardy9sap
               
        客户端下执行:
            变回主:slaveof no one 
            变回从:slaveof masterip masterport
        
(十四)Redis-Cluster集群
    
    Redis 3.0后,必须有3台Master + 3台Slave才能建立集群
    
    redis-cluster是无中心结构,
    每个节点保存数据和整个集群状态,
    每个节点都和其它节点连接。
    
    (虚拟环境下)部署流程:
        Step1: mkdir /usr/local/redis_cluster
        Step2: cd redis_cluster
        Step3: mkdir 700{1..6}
        Step4: cp -a ../redis/redis.conf ./7001
        Step5: vim ./7001/redis.conf 
               1. 将端口改为7001
               2. pidfile的6379改为7001
               3. requirepass hardy9sap
               3. 启用cluster: cluster-enabled yes
               4. 启用cluster-config-file, 并且将6379改为7001
               5. 启用cluster-node-timeout
        step6: 将7001下的redis.conf依次复制到7002 - 7006,并且将以上设置改为对应的数字
        Step7: 将redis解压目录下的src/复制到7001 - 7006中
        Step8: 将src中的redis-cli复制到/usr/local/bin下,方便操作
        Step9: 安装ruby
                yum -y install ruby ruby-devel rubygems rpm-build
                curl -L get.rvm.io | bash -s stable
                source ~/.bashrc
                source ~/.bash_profile
                find / -name rvm -print
                source /usr/local/rvm/scripts/rvm
                rvm list known
                rvm install install 2.6.3  (安装高于2.2.0即可)
        Step10: redis-cli --cluster create 192.168.1.102:7001 192.168.1.102:7002 192.168.1.102:7003
                                            192.168.1.102:7004 192.168.1.102:7005 192.168.1.102:7006 
                                            --cluster-replicas 1
                                            -a hardy9sap
        Step11: 客户端连接
                redis-cli -h 192.168.1.102 -p 7001 -c -a hardy9sap
                
                集群命令:
                    info replication    当前节点信息    
                    cluster nodes       查看所有的节点
                                            
    
    
    
    
    
    
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值