赞
踩
Redis作为当前主流的缓存组件,合理的运用将极大提高系统的性能
redis的优点,简单一个字就是 快
基于内存的存储让其吞吐量可以达到读的速度是110000次/s,写的速度是81000次/s(若使用SSD将更快)
save 60000 1 #表示60000s内有1次修改 就进行保存
手动存储
执行命令bgsave
缺点 数据过大时 非常慢
- appendonly yes
- appendfilename "appendonly.aof"
- #appendfsync always
- appendfsync everysec
- # appendfsync no
缺点 aof文件会非常大,但是可以保证数据不丢失通过lua脚本进行限流操作
- local key=KEYS[1]; --key
- local second = KEYS[2]; --单位s
- local total=KEYS[3]; --并发总数
-
-
- local count=redis.call("incr",key);
- local time=redis.call("ttl",key);
- local result=true;
- if(time==-1)
- then
- redis.call("expire",key,second);
- end
- if(tonumber(count)>tonumber(total))
- then
- result=false;
- end
- return tostring(result);
nodejs
- var fs = require("fs");
- var path = require("path");
- var lua = "";//lua脚本
- var sha = "";
-
- var redis = require("redis");
- var config = require("../../config");
- var log = require("../log4");
- var client;
- var clientoption = { host: config.config.redis.host, port: config.config.redis.port, password: config.config.redis.password, db: 2 };
- client = redis.createClient(clientoption);
- client.on("ready", function (err) {
- // redis.debug_mode = true;
- if (err) {
- console.log(err);
- } else {
- // console.log("redis read ok");
- log.logger.info("redis read ok");
- }
- });
- client.on("error", function (err) {
- // console.log(err, "出异常了");
- log.logger.error(err);
- })
- var privatehandler = {
- //整体逻辑
- flow: async function (key, second, total) {
- if (sha) {
- let d = await privatehandler.evalsha(sha, [3, key, second, total]);
- if (d == true) {
- return true;
- } else if (d == false) {
- return false;
- } else if (d == "NOSCRIPT") {
- if (!lua) {
- throw "lua文件不存在";
- }
- }
- }
- if (!lua) {
- lua = fs.readFileSync(path.resolve(__dirname, 'limitflow.lua')).toString();
- }
- sha = await privatehandler.evalload(lua);
- return await privatehandler.flow(key, second, total);
- },
- //根据hash值执行一个脚本 如果脚本不存在 会返回NOSCRIPT
- evalsha: async function (sha, command) {
- return new Promise(function (resolve, reject) {
- if (!command.constructor === Array) {
- reject("请传入参数数组");
- return;
- }
- command.unshift(sha);
- command.unshift("evalsha");
- // console.log(command);
- client.multi([command]).exec(function (err, result) {
- // console.log(err,result);
- if (err) {
- console.log(err);
- reject(err);
- }
- else {
- result = result[0];
- if (result == "true") {
- resolve(true);
- } else if (result == "false") {
- resolve(false);
- } else if (result && result.code == "NOSCRIPT") {//没有读取到数据
- resolve("NOSCRIPT");
- } else {
- reject(result);//其他异常
- }
- }
- });
- })
- },
- evalload: async function (luacontent) {//加载lua脚本 返回一个sha
- return new Promise(function (resolve, reject) {
- client.multi([["script", "load", luacontent]]).exec(function (err, result) {
- if (err) {
- console.log(err);
- reject(err);
- }
- else {
- result = result[0];
- resolve(result);
- }
- });
- })
- }
- }
- //封装给外部调用
- var handler = {
- /*
- key:关键key
- second:秒
- total:总数
- iswait:是否等待 如果不等待 将直接返回结果 如果等待 一直等到true
- */
- limitflow: async function (key, second, total, iswait) {
- if (!key || !second || !total || iswait == null) {
- throw "参数错误";
- }
- if (iswait) {
- while (!await privatehandler.flow(key, second, total)) {
- //如果不能继续执行 等10ms
- await sleep(10);
- }
- return true;
- } else {
- return await privatehandler.flow(key, second, total);
- }
- }
- }
-
- var sleep = function (time) {
- return new Promise(function (resolve, reject) {
- setTimeout(function () {
- resolve();
- }, time);
- })
- }
-
- exports.redisflow = handler;
redis的分布式锁主要是通过nx命令来实现,利用redis的原子性操作,若存在相同的键,操作将会失败,同时利用redis的自动过期功能,可防止因意外导致的锁释放异常,不会阻塞后续的锁获取。
各语言实现的分布式锁大同小异,不在赘述,一般java项目使用redission来实现分布式锁
主从配置非常简单,只要在从库里配置上主库信息即可slaveof 172.25.254.101 6379
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
首先配置Redis的主从服务器,修改redis.conf文件如下
- # 使得Redis服务器可以跨网络访问
- bind 0.0.0.0
- # 设置密码
- requirepass "123456"
- # 指定主服务器,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
- slaveof 192.168.11.128 6379
- # 主服务器密码,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
- masterauth 123456
上述内容主要是配置Redis服务器,从服务器比主服务器多一个slaveof的配置和密码。
配置3个哨兵,每个哨兵的配置都是一样的。在Redis安装目录下有一个sentinel.conf文件,copy一份进行修改
- # 禁止保护模式
- protected-mode no
- # 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.11.128代表监控的主服务器,6379代表端口,2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
- sentinel monitor mymaster 192.168.11.128 6379 2
- # sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
- # sentinel auth-pass <master-name> <password>
- sentinel auth-pass mymaster 123456
上述关闭了保护模式,便于测试。
有了上述的修改,我们可以进入Redis的安装目录的src目录,通过下面的命令启动服务器和哨兵
- # 启动Redis服务器进程
- ./redis-server ../redis.conf
- # 启动哨兵进程
- ./redis-sentinel ../sentinel.conf
注意启动的顺序。首先是主机(192.168.11.128)的Redis服务进程,然后启动从机的服务进程,最后启动3个哨兵的服务进程。
sentinel模式基本可以满足一般生产的需求,具备高可用性。但是当数据量过大到一台服务器存放不下的情况时,主从模式或sentinel模式就不能满足需求了,这个时候需要对存储的数据进行分片,将数据存储到多个Redis实例中。cluster模式的出现就是为了解决单机Redis容量有限的问题,将Redis的数据根据一定的规则分配到多台机器。
cluster可以说是sentinel和主从模式的结合体,通过cluster可以实现主从和master重选功能,所以如果配置两个副本三个分片的话,就需要六个Redis实例。因为Redis的数据是根据一定规则分配到cluster的不同机器的,当数据量过大时,可以新增机器进行扩容。
集群特点
- * 多个redis节点网络互联,数据共享
-
- * 所有的节点都是一主一从(也可以是一主多从),其中从不提供服务,仅作为备用
-
- * 不支持同时处理多个key(如MSET/MGET),因为redis需要把key均匀分布在各个节点上,
- 并发量很高的情况下同时创建key-value会降低性能并导致不可预测的行为
-
- * 支持在线增加、删除节点
-
- * 客户端可以连接任何一个主节点进行读写
开启配置
- #配置yes开启redis-cluster
- cluster-enabled yes
- #配置节点之间超时时间
- cluster-node-timeout 15000
- #这个配置很重要,cluster开启必须重命名指定cluster-config-file,不能与别的节点相同,否则会启动失败,最好按主机+端口命名
- cluster-config-file nodes-6379.conf
创建集群
redis-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1
若需要修正槽位,使用官方命令
redis-cli --cluster fix
执行命令检查集群
redis-cli --cluster info 127.0.0.1:6382
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。