redis-安装-配置说明-多实例-保护机制-持久化-同步-队列-事务-备份-复制-sentinel(哨兵)-集群
redis简介:
1、Redis是一款开源的,ANSI C语言编写的,高级键值(key-value)缓存和支持永久存储NoSQL数据库产品。 2、Redis采用内存(In-Memory)数据集(DataSet)。 3、支持多种数据类型。 4、运行于大多数POSIX系统,如Linux、*BSD、OS X等。 5、作者:Salvatore Sanfilippo
拷贝的简介,要想看的话,自己百度,很多这里就不介绍了,直接进入主题。
redis安装:
redis安装yum:
yum安装 配置文件在etc下 redis.conf
yum install -y epel-release # 扩展源下载 yum install -y redis #安装 systemctl enable redis #开机自动启动 systemctl start pedis #启动redis
redis安装源码包:
下载地址http://download.redis.io/releases/ #下载 yum install -y lrzsz #这个包是上传工具 tar -zxvf redis-3.2.6.tar.gz #解压 cd redis-3.2.6 #进入 make # 有可能报错 redis编译报致命错误:jemalloc/jemalloc.h:没有那个文件或目录 解决 make MALLOC=libc cp redis.conf ../redis6380/ #配置文件 cp src/redis-server ../redis6380/ #启动文件 主程序 ./redis-server ./redis.conf #启动
配置文件说明
egrep -v "^#|^$" redis.conf > redis.conf2 #配置文件去除开头带#跟空行 方法有很多 怎么熟悉怎么来 mv redis.conf redis.conf_bak #备份原配置文件 mv redis.conf2 redis.conf #覆盖原配置文件 vim redis.conf #修改端口等信息
bind ip地址 #就在内网上开 protected-mode yes #启动安全机制 requirepass root #结合安全机制 设置密码 demonize yes #(配置文件里面参数 后台启动) pidfile /var/run/redis_6380.pid #pid文件 logfile "/data/redis6380/redis.log" #日志文件 port 6379 #端口 appendonly no -> yes #日志开关 记录数据变化的 持久化策略开关 logfile stdout -> ./logs/redis.log #日志错误文件 dbfilename dump.rdb #持久化数据文件。相当于数据库的数据文件 rdbcompression yes #压缩 这些都是常用的配置,有些配置可以在redis内部用命令来设置
/usr/lib/systemd/system/redis.ervice (yum 安装的有 源码包安装没有)
简单的多实例
复制这个目录 修改端口 就是多实例 drwxr-xr-x 2 root root 96 7月 19 22:27 redis6380 drwxr-xr-x 2 root root 96 7月 19 22:31 redis6381
分别在这两个目录启动 tcp 0 0 127.0.0.1:6380 0.0.0.0:* LISTEN 13202/./redis-serve tcp 0 0 127.0.0.1:6381 0.0.0.0:* LISTEN 13228/./redis-serve
redis保护机制
修改完配置文件redis.conf protected-mode yes #启动安全机制 requirepass root #结合安全机制 设置密码
例子: 127.0.0.1:6380> get foo #需要认证 (error) NOAUTH Authentication required 127.0.0.1:6380> auth root #我来认证 OK 127.0.0.1:6380> get foo #成功 "guohongze"
持久化|策略
RDB 持久话可以在指定时间间隔内生成数据集的时间点快照(point-in-time-snapshot) AOF 持久化记录服务器执行的所有写操作的命令,并服务器启动时,通过重新执行这些命令来还原数据集。 save 900 1 save 300 10 save 60 10000 900秒(15分钟) 有一次操作的话 就保存一次 300秒(5分钟) 有十次操作的话 就保存一次 60秒(1分钟) 有10000次操作的话 就保存一次
同步
配置文件redis.conf appendfsync everysec no 表示等操作系统进行数据缓存同步到磁盘上linux约30秒 always 便是每次更新操作后调用fsunc()将数据写到磁盘 (慢 安全) everysec 表示每秒同步一次 (折中,默认值) 后期 优化可以考虑调整这些参数
redis高级应用 队列 | 订阅
发布消息通常有两种模式:(队列模式queuing 和发布-订阅模式publish-subscribe) 队列模式: consumers(消费者)可以同时从服务器端读取消息,每个消息只被其中一个consumer(消费者)读到。 发布-订阅模式: 中消息被广播到所有consumer(消费者)中,topic中的消息将被分发到组中的一个成员中。 同一组中的consumer可以在不同的程序中,也可以在不同的机器上。 队列模式例子: 127.0.0.1:6380> lrange bao 0 10 1) "bao6" 2) "bao5" 3) "bao4" 4) "bao3" 5) "bao2" 6) "bao1" 7) "bao" 127.0.0.1:6380> rpop bao #删除一个 "bao" 127.0.0.1:6380> rpop bao "bao1" 127.0.0.1:6380> rpop bao "bao2" 127.0.0.1:6380> lrange bao 0 10 #查看 1) "bao6" 2) "bao5" 3) "bao4" 4) "bao3" 127.0.0.1:6380> lpush bao bao7 #添加 (integer) 5 127.0.0.1:6380> lpush bao bao8 (integer) 6 127.0.0.1:6380> lpush bao bao9 (integer) 7 127.0.0.1:6380> lrange bao 0 10 1) "bao9" 2) "bao8" 3) "bao7" 4) "bao6" 5) "bao5" 6) "bao4" 7) "bao3" 先进先出 发布订阅模式: 发布订阅(pub/sub)是一种消息通讯模式:发送者(pud)发送消息,订阅者(sub)接收消息 redis 客户端可以订阅任意数量的频道 两台client端同时订阅 client1命令:subscribe wanghong #订阅网红 关注一个频道 网红频道 127.0.0.1:6380> SUBSCRIBE mq1 Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "mq1" 3) (integer) 1 1) "message" 2) "mq1" 3) "qing guan zhu wo " #这条消息是redis服务器端发布之后出现的 client2命令:subscribe wanghong 被订阅端发布一个消息 server命令:publish mq1 “qing guangzhu wo” 127.0.0.1:6380> publish mq1 "qing guan zhu wo " (integer) 2
redis事物
Redis 事务可以一次执行多个命令 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺地执行。 事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。 原子性:事务命令要么全部被执行,要么就全部都不执行 执行过程 开始事务 命令入队 执行事务 127.0.0.1:6380> ZADD salary 3000 guohongze 5000 oldboy 创建一个zadd的有序 集合 (integer) 2 127.0.0.1:6380> multi #标记一个事务块的开始 OK 127.0.0.1:6380> zincrby salary 1000 guohongze #添加事务一 guohongze加1000 QUEUED 127.0.0.1:6380> zincrby salary -1000 oldboy #添加事务二 oldboy减1000 QUEUED 127.0.0.1:6380> exec #执行所有事务块内的命令 1) "4000" 2) "4000" 127.0.0.1:6380> ZRANGE salary 0 -1 withscores #看一下有序集合的数据 1) "guohongze" 2) "4000" 3) "oldboy" 4) "4000" ####保证数据的一致性
redis慢日志查询
Slowlog 是redis用来记录查询执行时间的日志系统 Slowlog 保存在内存里面,读写速度非常快 可以通过改写redis.conf文件 后者 config get 和config set命令对他们动态地修改 slowlog-log-slower-than 10000 #超过多少微秒 #配置文件设置 config set slowlog-log-slower-then 100 #里面设置 config set slowly-max-len 1000 #保存多少条慢日志 Config get slow* #查询 Slowly get Slowly reset
redis数据备份
config get dir 获取当前目录 Save 备份(无持久化策略时),生成时在redis当前目录中。 恢复时只需将dump.db放入redis当前目录 (放入时候需要redis未启动,备份文件有数据或者在当前目录下,方可启动redis主程序) 当配置文件持久化关闭时(appendonly no)redis需要手动保存 直接save 就是产生dump.rdb 文件
redis复制(Replication)
config get dir 获取当前目录 Save 备份(无持久化策略时),生成时在redis当前目录中。 恢复时只需将dump.db放入redis当前目录 (放入时候需要redis未启动,备份文件有数据或者在当前目录下,方可启动redis主程序) 当配置文件持久化关闭时(appendonly no)redis需要手动保存 直接save 就是产生dump.rdb 文件 ------------redis复制(Replication)----------- 在从服务器删除旧版本数据集并载入新版本的数据集的那段时间内,链接请求会被阻塞 可以通过复制功能来让主服务器免于执行持久化操作,只要关闭主服务器的持久化功能,然后由从服务器去执行持久化操作即可。 避免一个问题: 1.假设节点A为主服务器,并且关闭了持久化,并且节点B和节点C从节点A复制 2.节点A崩溃,然后由自动拉起服务重启了节点A,由于节点A的持久化被关闭,所以重启之后没有任何数据 3.节点B和节点C将从节点A复制数据,但是A节点的数据是空的,于是就把自身保存的数据副本删除了 解决办法:没有自动拉起服务就好了 ------注意 积压空间问题---: 初次链接还是重新链接,当建立一个从服务器时,从服务器都将向主服务器发送一个sync命令。 接到sync命令的主服务器将开始bgsave,并在保存操作执行期间,将所有新执行的写入命令都报错到一个缓冲区里面。 当gbsave执行完毕后,主服务将执行保存操作所得的.rdb 文件发送给从服务器,从服务器接受这个.rdb文件,并将文件中的 数据载入到内存中 --------配置-------: 1。只需要在配置文件中增加一行: slaveof 192.168.1.1 6379 其中 92.168.1.1 和 6379 替换成你的主服务器的ip和端口 坏处:崩溃了 不敢重启 2.调用命令 slaveof 192.168.1.1 6379 即可 其中 92.168.1.1 和 6379 替换成你的主服务器的ip和端口 好处 你要重启了 手动命令 slaveof no one 将从变成主 ------手工主从切块------- 在原来的主上面关闭redis 在第一个从上面 slaveof no one 在第二台从 上面 添加 slaveof 192.168.1.1 6379 第一台从服务器的ip和端口 如果第一台开启了 那就成了从服务器了
redis sentinel(哨兵)
sentinel是redis官方推荐的高可用(HA)解决方案 1。监控(monitoring)Sentinel不断地检查你的主服务器和从服务器是否运作正常 2.提醒(notification)当被监控的某个redis服务器出现问题时,Sentinel可通过API向管理员或者其他应用程序发送通知。 3.自动故障迁移(Automatic failover):当一个主服务器不能正常工作时候,Sentinel会开始一次自动故障迁移操作,他会将失效主服务器的器中一个从服务升级为新的主服务器,并让失效的主服务器的其他从服务器改为复制新的主服务器;当客户端试图链接失效的主服务器时,集群也会向客户端返回新主服务器的地址,使得集群可以使用新主服务器代替失效服务器 mkdir S1 #创建一个目录 cp redis-3.2.6/sentinel.conf /data/S1/ #配置文件 cp redis-3.2.6/src/redis-sentinel /data/S1/ #主程序文件 sentinel 端口26379 -------------sentinel.conf配置文件---- sentinel monitor mymaster 127.0.0.1 6381 1 #有两个sentinel 最后的是2集群参数 sentinel auth-pass mymaster luyx30 #安全信息 sentinel down-after-milliseconds mymaster 10000 #1万毫秒 当主从切换多久后认为主从切换失败 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 180000 启动 ./redis-sentinel ./sentinel.conf 修改端口号 还有sentinel monitor mymaster 127.0.0.1 6381 2 最后一个参数修改成2
redis集群
Redis集群时一个可以在多个redis节点之间进行数据共享的设施(installation) Redis集群不支持那些需要同时处理多个键的redis命令,因为执行这些命令需要在多个redis节点之间移动数据,并且在高负载的情况下,这些命令将降低redis群集的性能,并导致不可预测的行为 Redis集群通过分区(partition)来提供一定程度的可用性(rvailability):即使集群中有一个部分节点失效后者无法进行通信,集群也可以继续处理命令请求 将数据自动切分(split)到多个节点的能力 当集群中的一部分节点失效或者无法进行通信时,仍然可以继续处理命令请求的能力 安装集群 16383个哈希槽 Yum install ruby rubygems -y gem install redis 如果卡住了使用国内镜像 gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org gem sources -l 配置文件redis.conf port 7000 #端口 cluster-enabled yes # cluster-node-timeout 5000 appendonly yes pidfile "/var/run/redis.pid" dir "./" 复制六个实例 for no in 0 1 2 3 4 5;do cp -r redis6380/ 700$no;done #复制实例 修改配置文件(这里有一个脚本) #!/bin/bash rm -rf /data/700* for no in 0 1 2 3 4 5;do cp -r redis6380/ 700$no;done for no in 0 1 2 3 4 5;do rm -rf /data/700$no/dump.rdb;done for no in 0 1 2 3 4 5 do cd /data/700$no sed -i "s/port 6380/port 7000/g" redis.conf echo "cluster-enabled yes" >> redis.conf echo "cluster-config-file nodes.conf" >> redis.conf echo "cluster-node-timeout 5000" >> redis.conf sed -i "s/appendonly no/appendonly yes/g" redis.conf sed -i "s/redis_6380.pid/redis_700$no.pid/g" redis.conf sed -i "s/^dir/d" redis.conf echo 'dir "./"' >>Reds.conf done for no in 0 1 2 3 4 5;do cd /data/700$no && ./redis-server ./redis.conf;done #启动 创建集群的命令: /data/redis-3.2.6/src/redis-trib.rb create --replicas 1 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 #--replicas 1 #几个从服务器 当前是一个 1.给定redis-trib.rb 程序的命令是create 这个表示我们希望创建一个新的集群 2.选项 --replicas 1 表示我们希望为集群中的每个主节点创建一个从节点 3.之后跟着的其他参数 则是实例的地址列表,我们希望程序使用这些地址所指示的实例来创建新集群 登陆集群 redis-cli -c -p 7000 # 必须加c 不加c参数登陆进去是有问题的 不加c是单机 集群状态 redis-cli -p 7000 cluster nodes |grep master 故障转移 redis-cli -p 7002 debug segfault 查看状态 redis-cli -p 7000 cluster nodes |grep master 重新分片 redis-trib.rb reshard 127.0.0.1:7000
命令
Redis-cli -p 6379 #进入(yum安装/usr/bin/redis ) 127.0.0.1:6380> set foo guohongze #创建一个键值对 127.0.0.1:6380> get foo #取出foo 对应的 值 127.0.0.1:6380> keys * #获取所有的key [root@localhost redis6380]# /data/redis-3.2.6/src/redis-cli -p 6380 #进入(源码安装) 127.0.0.1:6380> SHUTDOWN #停止服务 not connected> exit #退出
127.0.0.1:6380> auth root #我来认证 一种保护数据机制
关于redis配置命令
Info 服务器信息 client list 查看有一个客户端 client kill IP:port config get * config resetstat 重置统计 config get/set 动态修改 Dbsize flushall 清空所有数据 select 1 flushDB 清空当前库 Monitor 监控实时指令 最为常用 shutdown 关闭服务器 Save 将当前数据保存 slaveof host port 主从配置 slaveof no ond Sync 主从同步 Role 返回主从角色
redis一些简单的练习
------------------------字符串------------------------- ------set|get|type--- 127.0.0.1:6380> set name goujongze #创建一个name的键值对 OK 127.0.0.1:6380> get name #get name "goujongze" 127.0.0.1:6380> type name #查看类型 string 127.0.0.1:6380> 一个key 对应的值 最大能储存512MB ----append----- 127.0.0.1:6380> APPEND name 123 # 在值的尾部多加一个值 (integer) 12 127.0.0.1:6380> get name "goujongze123" ----Mset------- 127.0.0.1:6380> MSET name guohongze foo oldboy #同时设置一个或者多个键值对 OK 127.0.0.1:6380> MGET name foo 1) "guohongze" 2) "oldboy" 127.0.0.1:6380> ----strlen------- 127.0.0.1:6380> strlen name #字符串长度 (integer) 9 127.0.0.1:6380> get name "guohongze" 127.0.0.1:6380> ----incr|decr|incrby|decrby------- 127.0.0.1:6380> set age 33 OK 127.0.0.1:6380> 127.0.0.1:6380> INCR age #incr 加一 decr 减一 (integer) 34 127.0.0.1:6380> INCR age (integer) 35 127.0.0.1:6380> decr aghe (integer) -1 127.0.0.1:6380> decr aghe (integer) -2 127.0.0.1:6380> incrby age 100 #incrby|decrby 加一百 减一百 (integer) 137 127.0.0.1:6380> DECRBY age 100 (integer) 37 ----EXISTS------- 127.0.0.1:6380> EXISTS name #检查name是否存在 1 是存在 0 不存在 (integer) 1 127.0.0.1:6380> EXISTS asdasd (integer) 0 127.0.0.1:6380> ------------------------hash(哈希)------------------------- Redis hash 是一个键值对集合 Redis hash是一个string类型的field和value的映射表 Hash特别适合用于储存一个对象 每个hash可以储存 2^32-1 键值对 ----------hset| hgetall|hget| hget---------- 127.0.0.1:6380> hset user:1 name gouhongze #设置一个user:1对象 (integer) 1 127.0.0.1:6380> type user:1 hash 127.0.0.1:6380> hset user:1 age 35 (integer) 1 127.0.0.1:6380> hset user:1 sex male (integer) 1 127.0.0.1:6380> hgetall user:1 #get user:1 这个对象所有值 1) "name" 2) "gouhongze" 3) "age" 4) "35" 5) "sex" 6) "male" 127.0.0.1:6380> hget user:1 age #get 一个age 值 "35" 127.0.0.1:6380> hget user:1 name #get 一个name 值 "gouhongze" 127.0.0.1:6380> hmget user:1 name age #get 两个值 1) "gouhongze" 2) "35" --——————————---del---——————————————————--- 127.0.0.1:6380> keys * 1) "user:1" 2) "foo" 3) "name" 4) "aghe" 5) "oldboy" 6) "age" 127.0.0.1:6380> del oldboy #删除一个 (integer) 1 127.0.0.1:6380> keys * 1) "user:1" 2) "foo" 3) "name" 4) "aghe" 5) "age" --------------hdel-------————————————-- 127.0.0.1:6380> hdel user:1 age. #删除user:1 里面的age (integer) 1 127.0.0.1:6380> hgetall user:1 1) "name" 2) "xiaoqi" 3) "sex" 4) "male" ------------------------list(列表)------------------------- Redis列表是简单的字符串列表 按照插入顺序排序每个 List可以存储2^32-1 键值队 -------lpush|lrange----- 127.0.0.1:6380> LPUSH list1 bmw benz toyota honda #创建一个list1 (integer) 4 127.0.0.1:6380> type list1 #查看类型 list 127.0.0.1:6380> LRANGE list1 0 10 #便利一个列表 0是开始位 10结束位 1) "honda" 2) "toyota" 3) "benz" 4) "bmw" 127.0.0.1:6380> lpush list1 volvo #前面插入数据 (integer) 5 127.0.0.1:6380> rpush list1 byd #后面插入数据 (integer) 6 127.0.0.1:6380> lrange list1 0 10 #遍历一个list 1) "volvo" 2) "honda" 3) "toyota" 4) "benz" 5) "bmw" 6) "byd" -------rpop|lpop------- 127.0.0.1:6380> lrange list1 0 10 1) "volvo" 2) "honda" 3) "toyota" 4) "benz" 5) "bmw" 6) "byd" 127.0.0.1:6380> rpop list1 #最后的一个删除 "byd" 127.0.0.1:6380> lpop list1 #最前的一个删除 "volvo" 127.0.0.1:6380> LRANGE list1 0 10 1) "honda" 2) "toyota" 3) "benz" 4) "bmw" ----llen---- 127.0.0.1:6380> llen list1 #list长度 (integer) 4 127.0.0.1:6380> lrange list1 0 10 1) "honda" 2) "toyota" 3) "benz" 4) "bmw" -----------lrem-------- 127.0.0.1:6380> lrange list1 0 10 1) "bao8" 2) "bao7" 3) "bao6" 4) "bao6" 5) "bao5" 6) "bao4" 7) "bao3" 8) "bao2" 127.0.0.1:6380> lrem list1 1 bao6 #1数量 删除bao6 (integer) 1 127.0.0.1:6380> lrange list1 0 10 1) "bao8" 2) "bao7" 3) "bao6" 4) "bao5" 5) "bao4" 6) "bao3" 7) "bao2" ------lset------ 127.0.0.1:6380> lset list1 0 baozi001 修改list里面索引为0的元素 OK 127.0.0.1:6380> lrange list1 0 10 1) "baozi001" 2) "bao7" 3) "bao6" 4) "bao5" 5) "bao4" 6) "bao3" 7) "bao2" ------lindex------ 127.0.0.1:6380> lindex list1 0 "baozi001" --------linsert----- 127.0.0.1:6380> LINSERT list1 after bao5 bao6 #在baozi5后面插入baozi6 (integer) 8 127.0.0.1:6380> lrange list1 0 10 1) "baozi001" 2) "bao7" 3) "bao6" 4) "bao5" 5) "bao6" 6) "bao4" 7) "bao3" 8) "bao2"