Redis
介绍
Redis简介
-
Redis:Remote Dictionary Server(远程数据服务) -
Redis 是一个使用 C 语言写成的,由意大利人 antirez(Salvatore Sanfilippo) 开发的,开源的 key-value 数据库 -
属于Nosql 非关系数据库 -
它支持存储的value类型相对更多, 包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型) -
这些数据类型都支持 push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序 -
为了保证效率,数据都是缓存在内存中 -
redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步 -
官网:https://redis.io/ -
中文网:http://www.redis.cn/ -
作者github: https://github.com/antirez/redis
特点
- 速度快,redis虽然式单线程架构,但是由于redis的数据是运行在内存中的,所以redis的运行速度非常快
- 支持丰富的数据类型,具有五大基本数据类型
- 支持事务
- 丰富的功能特性
Redis应用场景
- 建过期功能:缓存,session会话保存,优惠券国企
- [List]列表:排行榜
- [String]天然计数器:帖子浏览数、视频播放数、评论留言数
- [Set]集合:兴趣标签,广告投放,共同好友
- 消息队列:ELK
- [Set]列表:防攻击系统(ip判断)黑白名单,文章列表
Memcached&Redis
- Redis不仅支持简单的k/v类型的数据,同时还支持list、set、zset(sorted set)、hash等数据结构的存储,使得它拥有更广阔的应用场景
- Redis最大的亮点是支持数据持久化,它在运行的时候可以将数据备份在磁盘中,断电或重启后,缓存数据可以再次加载到内存中,只要Redis配置的合理,基本上不会丢失数据
- Redis支持主从模式的应用
- Redis单个value的最大限制是1GB,而Memcached则只能保存1MB内的数据
- Memcache在并发场景下,能用cas保证事务一致性,而Redis事务支持比较弱,只能保证事务中的每个操作连续执行
- Memcached的内存管理不像Redis那么复杂,元数据metadata更小,相对来说额外开销就很少。Memcached唯一支持的数据类型是字符串string,非常适合缓存只读数据,因为字符串不需要额外的处理
- redis是单核,memcached是多核
安装与配置
redis源码安装
上传源码包
[root@redis soft]
[root@redis soft]
[root@redis soft]
安装
[root@redis redis-5.0.5]
启动
[root@redis redis-5.0.5]
[root@redis redis]
[root@redis bin]
设置redis后台启动
将配置文件复制到软件目录下
[root@redis bin]
修改配置文件
[root@redis bin]
136 daemonize yes
通过配置文件启动redis
[root@redis bin]
[root@redis bin]
添加到环境变量
[root@redis bin]
[root@redis bin]
配置文件介绍
[root@redis bin]
----------------------基础配置---------------------
bind 127.0.0.1 绑定IP地址
protected-mode yes
port 6379 监听端口
tcp-backlog 511
timeout 0 客户端连接超时时间
tcp-keepalive 300 检测客户端是否健康的周期时间
daemonize yes 是否以守护进程方式启动
supervised no
pidfile /var/run/redis_6379.pid 定义PID文件位置
loglevel notice 日志等级
logfile "" 日志文件位置
databases 16 数据库数目
always-show-logo yes 显示logo
----------------------RDB触发条件---------------------
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes 当启用了RDB且最后一次后台保存数据失败,Redis是否停止接收数据
rdbcompression yes 对于存储到磁盘中的快照,可以设置是否进行压缩存储
rdbchecksum yes 存储快照后,redis使用CRC64算法来进行数据校验
dbfilename dump.rdb 设置快照的文件名
dir ./ 设置快照文件的存放路径
----------------------主从复制---------------------
replica-serve-stale-data yes
replica-read-only yes 配置Redis的Slave实例是否只读
repl-diskless-sync no 主从数据复制是否使用无硬盘复制功能
repl-diskless-sync-delay 5 等待时间
repl-disable-tcp-nodelay no 同步之后是否禁用从站上的TCP_NODELAY
replica-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
----------------------AOF相关配置---------------------
appendonly no 默认redis使用的是rdb方式持久化
appendfilename "appendonly.aof" 文件名
appendfsync everysec aof持久化策略的配置
no-appendfsync-on-rewrite no 在aof重写或者写入rdb文件的时候,不执行持久化策略
auto-aof-rewrite-percentage 100 当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写
auto-aof-rewrite-min-size 64mb 设置允许重写的最小aof文件大小
aof-load-truncated yes 当截断的aof文件被导入的时候,会自动发布一个log给客户端然后load
aof-use-rdb-preamble yes
lua-time-limit 5000 一个lua脚本执行的最大时间
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
快速开始
客户端连接redis
[root@redis bin]
获取帮助
127.0.0.1:6379> help get
GET key
summary: Get the value of a key
since: 1.0.0
group: string
查看状态信息
127.0.0.1:6379> info
redis_version:5.0.5
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:56167a8ec7769013
redis_mode:standalone
os:Linux 2.6.32-696.el6.x86_64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:sync-builtin
gcc_version:4.4.7
process_id:5982
run_id:5f1c29e98feffe9c232282b464b0dc5d20ee4222
tcp_port:6379
uptime_in_seconds:454
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:7586498
executable:/usr/local/redis/bin/./redis-server
config_file:/usr/local/redis/bin/./redis.conf
connected_clients:1
client_recent_max_input_buffer:2
client_recent_max_output_buffer:0
blocked_clients:0
used_memory:855560
used_memory_human:835.51K
used_memory_rss:10653696
used_memory_rss_human:10.16M
used_memory_peak:4955080
used_memory_peak_human:4.73M
used_memory_peak_perc:17.27%
used_memory_overhead:842102
used_memory_startup:792408
used_memory_dataset:13458
used_memory_dataset_perc:21.31%
allocator_allocated:1396024
allocator_active:1724416
allocator_resident:8581120
total_system_memory:1028210688
total_system_memory_human:980.58M
used_memory_lua:37888
used_memory_lua_human:37.00K
used_memory_scripts:0
used_memory_scripts_human:0B
number_of_cached_scripts:0
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction
allocator_frag_ratio:1.24
allocator_frag_bytes:328392
allocator_rss_ratio:4.98
allocator_rss_bytes:6856704
rss_overhead_ratio:1.24
rss_overhead_bytes:2072576
mem_fragmentation_ratio:13.10
mem_fragmentation_bytes:9840392
mem_not_counted_for_evict:0
mem_replication_backlog:0
mem_clients_slaves:0
mem_clients_normal:49694
mem_aof_buffer:0
mem_allocator:jemalloc-5.1.0
active_defrag_running:0
lazyfree_pending_objects:0
loading:0
rdb_changes_since_last_save:0
rdb_bgsave_in_progress:0
rdb_last_save_time:1634975996
rdb_last_bgsave_status:ok
rdb_last_bgsave_time_sec:-1
rdb_current_bgsave_time_sec:-1
rdb_last_cow_size:0
aof_enabled:0
aof_rewrite_in_progress:0
aof_rewrite_scheduled:0
aof_last_rewrite_time_sec:-1
aof_current_rewrite_time_sec:-1
aof_last_bgrewrite_status:ok
aof_last_write_status:ok
aof_last_cow_size:0
total_connections_received:1
total_commands_processed:1
instantaneous_ops_per_sec:0
total_net_input_bytes:31
total_net_output_bytes:11468
instantaneous_input_kbps:0.00
instantaneous_output_kbps:0.00
rejected_connections:0
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:0
expired_stale_perc:0.00
expired_time_cap_reached_count:0
evicted_keys:0
keyspace_hits:0
keyspace_misses:0
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:0
migrate_cached_sockets:0
slave_expires_tracked_keys:0
active_defrag_hits:0
active_defrag_misses:0
active_defrag_key_hits:0
active_defrag_key_misses:0
role:master
connected_slaves:0
master_replid:5b1115898de78899bc6e2b787f68fcad3098c4c1
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0
used_cpu_sys:0.419936
used_cpu_user:0.209968
used_cpu_sys_children:0.000000
used_cpu_user_children:0.000000
cluster_enabled:0
简单使用
127.0.0.1:6379> set name zhangsan
OK
127.0.0.1:6379> get name
"zhangsan"
退出客户端
127.0.0.1:6379> quit
redis使用
- 命令手册: http://redisdoc.com/index.html
全局命令
- exists key:检查某个键是否存在,存在返回1,不存在返回0
127.0.0.1:6379> exists name
(integer) 1
127.0.0.1:6379> exists age
(integer) 0
127.0.0.1:6379> type name
string
- keys:查看所有键,该命令在生产环境中慎用,会一次性读取所有键,可能会导致阻塞
127.0.0.1:6379> keys *
1) "id"
2) "name"
3) "hobby"
127.0.0.1:6379> expire id 10
(integer) 1
127.0.0.1:6379> ttl id
(integer) 5
127.0.0.1:6379> ttl id
(integer) 2
127.0.0.1:6379> ttl id
(integer) 1
127.0.0.1:6379> ttl id
(integer) -2
- del key:删除键,可以只删除一个键也可以同时删除多个键,删除成功后会返回成功删除键的个数,删除失败会返回0
127.0.0.1:6379> del hobby name
(integer) 2
- select index:选择数据库,默认在redis中,提供了16库(0-15),可在配置文件中更改
- dbsize:查看当前数据库中的所有键的数量
127.0.0.1:6379> select 0
OK
127.0.0.1:6379> dbsize
(integer) 3
127.0.0.1:6379> select 15
OK
127.0.0.1:6379[15]> dbsize
(integer) 0
- flushdb:清空当前库
- flushall:清空所有库
127.0.0.1:6379[15]> flushdb
OK
127.0.0.1:6379[15]> flushall
OK
127.0.0.1:6379[15]> keys *
(empty list or set)
127.0.0.1:6379[15]> move name 0
(integer) 1
String
字符串类型是redis最基础的数据结构,而且其他集中数据结构都是在字符串类型基础上构建的
- set key value:添加键值对
- mset k1 v1 k2 v2:批量添加键值对
- setrange key offeset value :设置指定位置的字符
127.0.0.1:6379[15]> set k1 v1
OK
127.0.0.1:6379[15]> mset name zhangsan age 12
OK
127.0.0.1:6379[15]> setrange k1 1 v
(integer) 2
127.0.0.1:6379[15]> get k1
"vv"
- get key:获取键对应的值
- mget key:批量获取键对应的值
- getrange key start end:获取部分字符串
127.0.0.1:6379[15]> get name
"zhangsan"
127.0.0.1:6379[15]> mget name age
1) "zhangsan"
2) "12"
127.0.0.1:6379[15]> getrange name 0 4
"zhang"
- incr key:自增1
- 值不是整数,返回错误
- 值是整数,返回自增后的结果
- 键不存在,按照值为0自增,返回结果为1
- incrby key integer:同incr,自增指定值
- decr key:自减1
- 值不是整数,返回错误
- 值是整数,返回自减后的结果
- 键不存在,按照值为0自减,返回结果为-1
- decrby key integer:同decr,自减指定值
127.0.0.1:6379[15]> incr age
(integer) 13
127.0.0.1:6379[15]> incr age
(integer) 14
127.0.0.1:6379[15]> incrby age 10
(integer) 24
127.0.0.1:6379[15]> decrby age 5
(integer) 19
127.0.0.1:6379[15]> incr num
(integer) 1
127.0.0.1:6379[15]> decr num1
(integer) -1
- append key value:向字符串尾部追加值
127.0.0.1:6379[15]> append name +lisi
(integer) 13
127.0.0.1:6379[15]> get name
"zhangsan+lisi"
127.0.0.1:6379[15]> get name
"zhangsan+lisi"
127.0.0.1:6379[15]> strlen name
(integer) 13
list
列表(list)类型是用来存储多个有序的字符串,是一种线性结构可以充当栈(先进后出)和队列(先进先出)的角色
头部(左 left) 尾部(右right)
- lpush key value:从左边插入元素
- rpush key value:从右边插入元素
127.0.0.1:6379[15]> lpush list1 aa
(integer) 1
127.0.0.1:6379[15]> lpush list1 bb
(integer) 2
127.0.0.1:6379[15]> lpush list1 cc
(integer) 3
127.0.0.1:6379[15]> lpush list1 dd
(integer) 4
- lpop key:从左边弹出(删除)元素
- rpop key:从右边弹出(删除)元素
127.0.0.1:6379[15]> lpop list1
"dd"
127.0.0.1:6379[15]> lpop list1
"cc"
127.0.0.1:6379[15]> rpop list1
"aa"
- lrange key start end:获取指定范围内的元素列表
- lindex key index:获取列表指定索引下标的元素
- llen key:获取列表长度
- ltrim key start end:按照索引范围修剪列表
127.0.0.1:6379[15]> lrange list1 0 2
1) "ff"
2) "ee"
3) "bb"
127.0.0.1:6379[15]> lindex list1 -1
"bb"
127.0.0.1:6379[15]> llen list1
(integer) 3
127.0.0.1:6379[15]> ltrim list1 1 -1
OK
127.0.0.1:6379[15]> lrange list1 0 -1
1) "ee"
2) "bb"
- lset key index newvalue:修改指定索引下标的元素
127.0.0.1:6379[15]> lset list1 0 hello
OK
127.0.0.1:6379[15]> lrange list1 0 -1
1) "hello"
2) "bb"
set
集合(set)类型也是用来保存多个的字符串元素,集合中不允许有重复出现的元素,集合的元素是没有顺序的不能够通过下标来获得值
127.0.0.1:6379[15]> sadd myset a b c e g k
(integer) 6
127.0.0.1:6379[15]> sadd yourset b c d m n k
(integer) 6
- srem key element:删除元素;如果元素不存在,返回0
127.0.0.1:6379[15]> srem myset a e
(integer) 2
127.0.0.1:6379[15]> srem myset hello
(integer) 0
127.0.0.1:6379[15]> scard myset
(integer) 4
127.0.0.1:6379[15]> scard yourset
(integer) 6
- sismember key element:判断元素是否在集合中,如果给定元素element在集合内返回1,反之返回0
127.0.0.1:6379[15]> sismember myset c
(integer) 1
127.0.0.1:6379[15]> sismember myset y
(integer) 0
- srandmember key [count]:随机从集合中返回指定元素个数,[count]是可选参数,如果不写默认为1
- smembers key:获取集合中所有元素
127.0.0.1:6379[15]> srandmember yourset 2
1) "m"
2) "d"
127.0.0.1:6379[15]> srandmember yourset
"d"
127.0.0.1:6379[15]> smembers myset
1) "k"
2) "b"
3) "g"
4) "c"
- spop key :从集合中随机弹出(删除)一个元素
127.0.0.1:6379[15]> spop myset
"k"
127.0.0.1:6379[15]> smembers myset
1) "b"
2) "g"
3) "c"
- sinter key [key …] :交集运算
- sinterstore destination key [key …] :保存交集运算的结果
- suinon key [key …]:并集运算
- suinonstore destination key [key …]:保存并集运算的结果
- sdiff key [key …]:差集运算
- sdiffstore destination key [key …]:保存差集运算的结果
127.0.0.1:6379[15]> sinter myset yourset
1) "b"
2) "c"
127.0.0.1:6379[15]> sinterstore inter_set myset yourset
(integer) 2
127.0.0.1:6379[15]> smembers inter_set
1) "c"
2) "b"
127.0.0.1:6379[15]> sunion myset yourset
1) "m"
2) "n"
3) "k"
4) "b"
5) "g"
6) "d"
7) "c"
127.0.0.1:6379[15]> sunionstore union_set myset yourset
(integer) 7
127.0.0.1:6379[15]> smembers union_set
1) "m"
2) "n"
3) "k"
4) "b"
5) "g"
6) "d"
7) "c"
127.0.0.1:6379[15]> sdiff myset yourset
1) "g"
127.0.0.1:6379[15]> sdiffstore diff_set myset yourset
(integer) 1
127.0.0.1:6379[15]> smembers diff_set
1) "g"
127.0.0.1:6379[15]> sdiff yourset myset
1) "m"
2) "d"
3) "n"
4) "k"
zset
有序集合保留了集合不能有重复成员的特性,不同的是有序集合中的元素是可以排序的。但是它和列表使用索引下标作为排序依据不同的是它给每个元素设置一个分数(score)作为排序的依据
数据存在内存中,速度快
- zadd key score member [score member …]:添加成员
127.0.0.1:6379[15]> zadd user:ranking 251 tom
(integer) 1
127.0.0.1:6379[15]> zadd user:ranking 1 kris 91 mike 200 frank 220 tim 250 martin
(integer) 5
- zcard key:计算成员个数
- zscore key member:计算某个成员的分数
127.0.0.1:6379[15]> zcard user:ranking
(integer) 6
127.0.0.1:6379[15]> zscore user:ranking kris
"1"
- zrank key member :计算某个成员的排名,分数从低到高
- zrevrank key member :计算某个成员的排名,分数从高到低
127.0.0.1:6379[15]> zrank user:ranking kris
(integer) 0
127.0.0.1:6379[15]> zrevrank user:ranking kris
(integer) 5
- zrem key member [member …]:删除成员
127.0.0.1:6379[15]> zrem user:ranking kris
(integer) 1
- zincrby key increment member :增加成员的分数
127.0.0.1:6379[15]> zincrby user:ranking 9 tom
"260"
- zrange key start end [withscores]:返回指定排名范围的成员,如果加上withscores选项,同时会返回成员的分数
- zrangebyscore key min max [withscores]:返回指定分数范围的成员,withscores选项会同时返回每个成员的分数
- zcount key min max :返回指定分数范围的成员个数
127.0.0.1:6379[15]> zrange user:ranking 0 2
1) "mike"
2) "frank"
3) "tim"
127.0.0.1:6379[15]> zrange user:ranking 0 2 withscores
1) "mike"
2) "91"
3) "frank"
4) "200"
5) "tim"
6) "220"
127.0.0.1:6379[15]> zrevrangebyscore user:ranking 221 200
1) "tim"
2) "frank"
127.0.0.1:6379[15]> zrevrangebyscore user:ranking 221 200 withscores
1) "tim"
2) "220"
3) "frank"
4) "200"
127.0.0.1:6379[15]> zcount user:ranking 200 221
(integer) 2
hash
几乎所有编程语言都提供了hash类型,他们的叫法可能是哈希、字典、关联数组。常常会使用hash数据类型存储关系型数据库中的表
使用redis做缓存,可以使用hash结构,压缩效率和使用效率比string更高
127.0.0.1:6379[15]> hset user:1 name lili age 20 sex female
(integer) 3
- hget key field:获取某个field的值
- hgetall key:获取所有值
- hkeys key :获取所有field
- hvals key:获取所有value
- hlen key:获取field个数
- hmget key field [field …]:批量获取field-value
127.0.0.1:6379[15]> hget user:1 name
"lili"
127.0.0.1:6379[15]> hgetall user:1
1) "name"
2) "lili"
3) "age"
4) "20"
5) "sex"
6) "female"
127.0.0.1:6379[15]> hkeys user:1
1) "name"
2) "age"
127.0.0.1:6379[15]> hvals user:1
1) "lili"
2) "20"
127.0.0.1:6379[15]> hlen user:1
(integer) 3
127.0.0.1:6379[15]> hmget user:1 name age
1) "lili"
2) "20"
- hdel key field [field …] :删除field
127.0.0.1:6379[15]> hdel user:1 sex
(integer) 1
127.0.0.1:6379[15]> hgetall user:1
1) "name"
2) "lili"
3) "age"
4) "20"
- hexists key field:判断field是否存在
127.0.0.1:6379[15]> hexists user:1 age
(integer) 1
127.0.0.1:6379[15]> hexists user:1 hobby
(integer) 0
数据持久化
- 数据若只存在内存中,服务重启后会丢失,如果想实现持久化,就需要把数据存储到磁盘中
snappshoting(快照)
- 默认snappshoting是开启的,有一个备份的频率。通过查看配置文件可以看到
[root@redis bin]
save 900 1
save 300 10
save 60 10000
-
备份频率
- 900s(15min)最少有1个key发生改变
- 300s(5min)最少有10个key发生改变
- 60s(1min)最少有10000个key发生改变
-
备份文件位置
[root@redis bin]
dbfilename dump.rdb
[root@redis bin]
dump.rdb
127.0.0.1:6379[15]> save
- 通过备份文件恢复数据:停掉redis服务,将备份文件 (dump.rdb) 移动到 redis 安装目录并启动服务即可
- snappshoting 一般的数据持久化使用,效率高,数据迁移方便
append only file(aof)
[root@redis bin]
appendonly no
appendfilename "appendonly.aof"
appendfsync everysec
- 开启aof后,之前的redis里的数据会丢失,数据每秒备份一次
- aof 适合于备份、数据实时性备份要求更高的情况。开启aof后,redis读写效率下降
常用案例
主从复制
- 环境准备(基于server08克隆server09)
虚拟机 | 主机名 | ip地址 |
---|
server08 | cache1.master | 192.168.139.135 | server09 | cache2.slave | 192.168.139.136 |
[root@cache1 ~]
69 bind 127.0.0.1 192.168.139.135
[root@cache1 ~]
[root@cache1 ~]
LISTEN 0 128 192.168.139.135:6379 *:* users:(("redis-server",1732,7))
LISTEN 0 128 127.0.0.1:6379 *:* users:(("redis-server",1732,6))
[root@cache2 ~]
286
287 replicaof 192.168.139.135 6379
注意:在redis5.0之前,该配置为slaveof 192.168.139.135 6379
由于slave具有奴隶的含义,出于人权考虑,在redis5.0版本后废止
[root@cache2 ~]
[root@cache1 ~]
127.0.0.1:6379> info Replication
role:master
connected_slaves:1
slave0:ip=192.168.139.136,port=6379,state=online,offset=70,lag=1
master_replid:49f5bfeb74098f0c1752f8cf557a4b77e7c37d61
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:70
[root@cache2 ~]
127.0.0.1:6379> info replication
role:slave
master_host:192.168.139.135
master_port:6379
master_link_status:up
master_last_io_seconds_ago:11
master_sync_in_progress:0
slave_repl_offset:126
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:49f5bfeb74098f0c1752f8cf557a4b77e7c37d61
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:126
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:126
安全限制
IP限制登录
绑定允许登录的IP
[root@cache1 ~]
bind 127.0.0.1 192.168.139.135
密码验证
设置密码
[root@cache1 ~]
507
508 requirepass 123456
[root@cache1 ~]
[root@cache1 ~]
验证
[root@cache2 ~]
192.168.139.135:6379> set k1 v1
(error) NOAUTH Authentication required.
登录失败,需要密码
192.168.139.135:6379> auth 123456
OK
192.168.139.135:6379> set k1 v1
OK
master设置密码后,slave上显示master_link_status:down
[root@cache2 ~]
127.0.0.1:6379> info replication
role:slave
master_host:192.168.139.135
master_port:6379
master_link_status:down
master_last_io_seconds_ago:-1
master_sync_in_progress:0
slave_repl_offset:1
master_link_down_since_seconds:267
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:49f5bfeb74098f0c1752f8cf557a4b77e7c37d61
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:22694
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:22694
在slave上配置master的密码
[root@cache2 ~]
293
294 masterauth 123456
[root@cache2 ~]
[root@cache2 ~]
查看
[root@cache2 ~]
127.0.0.1:6379> info replication
role:slave
master_host:192.168.139.135
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:14
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:ed6c50688b958c3fb87d6c11b6cd1aff152f3a06
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:14
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:14
PHP扩展安装
rz
tar -xzf redis-4.3.0.tgz
cd redis-4.3.0
phpize
./configure && make && make install
ls /usr/local/php/lib/php/extensions/no-debug-zts-20170718/
vim /usr/local/php/etc/php.ini
service php-fpm reload
session共享
vim /usr/local/nginx/html/tp5shop/application/config.php
205 'session' => [
206 'id' => '',
207 // SESSION_ID的提交变量,解决flash上传跨域
208 'var_session_id' => '',
209 // SESSION 前缀
210 'prefix' => 'think',
211 // 驱动方式 支持redis memcache memcached
212 'type' => 'redis',
213 // 连接memcached的主机
214 'host' => '192.168.139.135',
215 'password' => '123456',
216 // 是否自动开启 SESSION
217 'auto_start' => true,
218 ],
service nginx reload
[root@cache1 ~]
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> keys *
1) "k1"
2) "6vb52043vj9bgu16bt2ta2a8vc"
127.0.0.1:6379> get 6vb52043vj9bgu16bt2ta2a8vc
"d2d977c58444271d9c780187e93f80e5|a:2:{s:11:\"verify_code\";s:32:\"58fb158d7f03267e2fbb625c38d8f29c\";s:11:\"verify_time\";i:1634778545;}"
Nginx+lua+redis实现访问攻击黑名单WAF(动态防火墙)
参考文档:https://www.cnblogs.com/huligong1234/p/4163832.html
- 安装openresty(nginx加强版),安装步骤略(nginx章节有详细说明)
- 上传并修改lua脚本文件
[root@web ~]
[root@web conf]
[root@web conf]
7 -- 连接redis
8 red.connect(red, '192.168.139.135', '6379')
9 -- redis的密码
10 red:auth("d123456")
[root@web conf]
-- access_by_lua_file '/usr/local/lua_test/my_access_limit.lua';
ngx.req.read_body()
-- 引入redis的包
local redis = require "resty.redis"
-- 实例化
local red = redis.new()
-- 连接redis
red.connect(red, '192.168.139.135', '6379')
-- redis的密码
red:auth("123456")
-- 用户的真实IP
local myIP = ngx.req.get_headers()["X-Real-IP"]
if myIP == nil then
myIP = ngx.req.get_headers()["x_forwarded_for"]
end
if myIP == nil then
myIP = ngx.var.remote_addr
end
-- 匹配需要验证的URI
if ngx.re.match(ngx.var.uri,"/index.html") then
-- 校验IP是否存在黑名单中
local hasIP = red:sismember('black.ip',myIP)
-- 在黑名单
if hasIP==1 then
-- ngx.say("This is 'Black List' request")
ngx.exit(ngx.HTTP_FORBIDDEN)
end
--如果访问超过10次 就加入IP到黑名单
local count = red:get(myIP)
if count == ngx.null then
count = 0
end
if (tonumber(count)>7) then
red:sadd('black.ip',myIP)
end
--每次访问+1
red:incr(myIP)
end
[root@web conf]
/usr/local/openresty/nginx/conf
[root@web conf]
43 location / {
44 root html;
45 index index.html index.htm;
46 access_by_lua_file /usr/local/openresty/nginx/conf/access_by_lua
47 }
[root@web conf]
[root@web conf]
127.0.0.1:6379> keys *
1) "k1"
2) "black.ip"
3) "192.168.139.1"
4) "6vb52043vj9bgu16bt2ta2a8vc"
127.0.0.1:6379> type black.ip
set
127.0.0.1:6379> smembers black.ip
1) "192.168.139.1"
|