rediscommand(rediscommand设计模式)
本篇文章给大家谈谈rediscommand,以及rediscommand设计模式对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、c#连接redis客户端怎么释放连接数
- 2、redis--安全
- 3、redis┃面试官问我redis事务和mysql事务的区别,我
- 4、Redis 启动警告解决方法
- 5、redis是如何执行的
- 6、bash:redis-server:command not found是什么情况
c#连接redis客户端怎么释放连接数
redis允许客户端以TCP方式连接,默认6379端口。传输数据都以\r\n结尾。
请求格式
*number of arguments\r\n$number of bytes of argument 1\r\nargument data\r\n
例虚档腔:*1\r\n$4\r\nINFO\r\n
响应格式
1:简单字符串,非二进蠢瞎制安全字符串,一般是状态回复。 +开头,例:+OK\r\n
2: 错误信息。-开头, 例:-ERR unknown command 'mush'\r\n
3: 整型数字。 :开头, 例::1\r\n
4:大块回复值,最大512M。 $开头+数据长度。 例:$4\r\mush\r\n
5:多条回复。 *开头, 例:*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n
基础通信
定义配置类:
public class Configuration
{
public string Host { get; set; }
public int Port { get; set; }
/// summary
/// Socket 是否正在使用 Nagle 算法。
/// /差衫summary
public bool NoDelaySocket { get; set; }
public Configuration()
{
Host = "localhost";
Port = 6379;
NoDelaySocket = false;
}
}
实现socket连接:
public class RedisBaseClient
{
//配置文件
private Configuration configuration;
//通信socket
private Socket socket;
//接收字节数组
private byte[] ReceiveBuffer = new byte[100000];
public RedisBaseClient(Configuration config)
{
configuration = config;
}
public RedisBaseClient()
: this(new Configuration())
{
}
public void Connect()
{
if (socket != null socket.Connected)
return;
socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
{
NoDelay = configuration.NoDelaySocket
};
socket.Connect(configuration.Host, configuration.Port);
if (socket.Connected)
return;
Close();
}
/// summary
/// 关闭client
/// /summary
public void Close()
{
socket.Disconnect(false);
socket.Close();
}
}
调用:
RedisBaseClient redis = new RedisBaseClient();
redis.Connect();
服务端成功响应:
状态命令
定义Redis命令枚举:
public enum RedisCommand
{
GET, //获取一个key的值
INFO, //Redis信息。
SET, //添加一个值
EXPIRE, //设置过期时间
MULTI, //标记一个事务块开始
EXEC, //执行所有 MULTI 之后发的命令
}
发送命令构建:
public string SendCommand(RedisCommand command, params string[] args)
{
//请求头部格式, *number of arguments\r\n
const string headstr = "*{0}\r\n";
//参数信息 $number of bytes of argument N\r\nargument data\r\n
const string bulkstr = "${0}\r\n{1}\r\n";
var sb = new StringBuilder();
sb.AppendFormat(headstr, args.Length + 1);
var cmd = command.ToString();
sb.AppendFormat(bulkstr, cmd.Length, cmd);
foreach (var arg in args)
{
sb.AppendFormat(bulkstr, arg.Length, arg);
}
byte[] c = Encoding.UTF8.GetBytes(sb.ToString());
try
{
Connect();
socket.Send(c);
socket.Receive(ReceiveBuffer);
Close();
return ReadData();
}
catch (SocketException e)
{
Close();
}
return null;
}
private string ReadData()
{
var data = Encoding.UTF8.GetString(ReceiveBuffer);
char c = data[0];
//错误消息检查。
if (c == '-') //异常处理。
throw new Exception(data);
//状态回复。
if (c == '+')
return data;
return data;
}
redis--安全
[TOC]
redis被设计成仅有可信环境下的可信用户才可以访问。这意味着将redis实例直接暴露在网络上或者让不可信用户直接访问redis的是不安全的。
==换句话说,redis不保证redis的安全,而是由使用者保证的。==
在redis的配置文件中,可以配置==bind==的ip,让redis只接受绑定的ip的客户端。
一般来说,如果redis需要禁止外部访问,只需bind本地IP即可。
bind 127.0.0.1
也可饥贺以绑定指定的网段:
bind 192.168.1.100 10.0.0.1
在redis的配置文件中可以配置
requirepass password 来配置验证密码。
当配置了验证密码后,在开始执行其他命令之前需要执行 auth password 来验证。
使用 config get requ* 获取配置信息
发现有两个返回,分别是 requirepass 和空,意思是,requirepass现在的配凳哗置为空,表示不启用
使用 config set requirepass mypassword 设置密码是mypassword
然后我们退出客户端,然后重新登录
连接是没有问题的,但是却无法执行任何命令。
使用auth验证通过后,才能执行redis的命令。
但是这种方式也存在问题:
redis每秒可以尝试15W的密码,所以如果密码长度比较短的话,很短时间就会被暴力破解。
735 091 890 625 / 150000 = 4 900 612.6 秒 = 81 676.88 分 = 1361.28时 = 56.72天
看起来还不错吧,假设一个机器有4个核心,8线程。那么在一个机器上同时开8个客户端,每个客户端负责尝试指定范围的密码组合。
56.72 / 8 = 7.09 天
如果有多台机器,那么速度会更快。假设有100台机器,每台的机器配置都一样:
7.09 / 100 = 15.696 分钟
==你设置的密码,在强大的算力下,只需15分钟的时间就会被破解。==
当然,这只是理论上的,实际烂粗派上还需要考虑网络,多线程切换等因素影响。
==AUTH 命令在网络中是明文传输的。==
如果你登录了redis,意味着,redis中全部的命令你都能使用。对于普通用户来说,使用一些高危的操作很危险,所以需要对普通用户禁用一些命令。
redis是通过==命令重命名==来实现命令禁用的
rename-command source-command dest-command
通过配置 rename-command 将 source-command 重命名为 dest-command
后面想要使用 source-command 只能输入 dest-command 来使用了。
对于普通用户来说,不知道 dest-command ,就无法使用 source-command 了。
如果 dest-command 设置为空,表示任何人都无法使用 source-command 了。
redis┃面试官问我redis事务和mysql事务的区别,我
1、前言
面试官:我看你简历上写了熟悉redis,看来工作中用的很多吧?
我:是的,我们项目中经常用到redis(来,随便问,看我分分钟秒杀你)
面试官:那你给我说说redis的事务和mysql的事务有什么区别吧
我:额。。。事务还有区别????
面试官:比如说redis的事务是不支持原子性和持久性的,包括他们的实现原理等方面也是有很大区别的。
我:学到了。。。。。。
2、正文
事务的四大特性
ACID,指数据库事务正确执行的四个基本要素的缩写。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
说的是一个事物内所有操作就是最小的一个操作单元,要么全部成功,要么全部失败。这是最基本的特性,保证了因为一些其他因素导致数据库异常,或者宕机。
一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。
一致性有下面特点:
在现实中,事务系统遭遇并发请求时,这种串行化是有成本的, Amdahl法则描述如下:它是描述序列串行执行和并发之间的关系。
“一个程序在并行计算情况下使用多个处理器所能提升的速度是由这个程序中串行执行部分的时间决定的。”
大多数数据库管理系统选择(默认情况下)是放宽一致性,以达到更好的并发性。
事物的隔离性,基于原子性和一致性,因为事物是原子化,量子化的,所以,事物可以有多个原子包的形式并发执行,但是,每个事物互不干扰。
但是,由于升余多个事物可能操作同一个资源,不同的事物为了保证隔离性,会有很多锁方案,当然这是数据库的实现,他们怎么实现的,我们不必深究。
持久性,当一个事物提交之后,数据库状态永远的发生了改变,即这个事物只要提交了,哪怕提交后宕机,他也确确实实的提交了,不会出现因为刚刚宕机了而让提交不生效,是要事物提交,他就像洗不掉的纹身,永远的固化了,除非你毁了硬盘。
事务命令
mysql:
Begin:显式的开启一个事务
Commit:提交事务,将对数据库进行的所有的修改变成永久性
Rollback:结束用户的事务,并撤销现在正在进行的未提交的修改
redis:
Multi:标记事务的开始
Exec:执行事务的commands队列
Discard:结束事务,并清除commands队列
默认状态
mysql:
mysql会默认开启一个事务,且缺省设置是自动提交,即每成功执行sql,一个事务就会马上commit,所以不能rollback,
redis:
redis默认不会开启事务,即command会立即执行,而不会排队,并不支吵神滚持rollback
使用方式
mysql(包含两种方式):
用Begin、Rollback、commit显式开启并控制一个 新的 Transaction
执行命令 set autocommit=0,用来禁止当前会话自动commit,瞎野控制 默认开启的事务
redis:
用multi、exec、discard,显式开启并控制一个Transaction。
(注意:这里没有强调 “新的” ,因为默认是不会开启事务的)。
实现原理
mysql:
mysql实现事务,是基于undo/redo日志
undo记录修改前状态,rollback基于undo日志实现
redo记录修改后的状态,commit基于redo日志实现
既然是基于redo日志实现记录修改后的状态,那么大家应该也知道,redo日志是innodb专有的,所以innodb会支持事务
在mysql中无论是否开启事务,sql都会被立即执行并返回执行结果,只是事务开启后执行后的状态只是记录在redo日志,执行commit之后,数据才会被写入磁盘
(以上内容后面我会详细在mysql篇给大家讲到,大家可以先简单了解下)
所以,上述代码,insertSelective 将会被立即赋值(无论是否开启事务,只是结果或未被写入磁盘):
redis:
redis实现事务,是基于commands队列
如果没有开启事务,command将会被立即执行并返回执行结果,并且直接写入磁盘
如果事务开启,command不会被立即执行,而是排入队列,并返回排队状态(具体依赖于客户端(例如:spring-data-redis)自身实现)。
调用exec才会执行commands队列
以上代码如果没有开启事务,操作被立即执行,a将会被立即赋值(true/false)
如果开启事务,操作不会被立即执行,将会返回null值,而a的类型是boolean,所以将会抛出异常:
Redis事务不支持Rollback(重点)
事实上Redis命令在事务执行时可能会失败,但仍会继续执行剩余命令而不是Rollback(事务回滚)。如果你使用过关系数据库,这种情况可能会让你感到很奇怪。然而针对这种情况具备很好的解释:
redis 事务中的错误
事务期间,可能会遇到两种命令错误:
客户端会在EXEC调用之前检测第一种错误。 通过检查排队命令的状态回复(***注意:这里是指排队的状态回复,而不是执行结果***),如果命令使用QUEUED进行响应,则它已正确排队,否则Redis将返回错误。如果排队命令时发生错误,大多数客户端将中止该事务并清除命令队列。然而:
这是由于INCR命令的语法错误,将在调用EXEC之前被检测出来,并终止事务(version2.6.5+)。
EXEC命令执行之后发生的错误并不会被特殊对待:即使事务中的某些命令执行失败,其他命令仍会被正常执行。
Redis 启动警告解决方法
第一个问题: Increased maximum number of open files to 10032 (it was originally set to 1024).
原因分析:即进程能打开的最大文件描述符太小了。系统默认设置的值一般是 1024 。
解决方法:
1.系统级别,即 linux 内核能分配的最大文件描述符数量(参考:)。
# vi /etc/sysctl.conf
fs.file-max = 102400
# sysctl -p
查看方法:
# cat /proc/sys/fs/file-max
# sysctl fs.file-max
2.用户级别,即用户进程能打开哗巧察的最大文件描述符数量(参考 man limits.conf 或者 )。
设置方法:
# vi /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
查看方法(无需重启系统乱茄。当前用户重新登录后生效。或者切换到具体的用户,立刻生效):
# su - username
$ ulimit -Hn
$ ulimit -Sn
注意:
CentOS 还需开启 pam_limits 模块,因为 limits.conf 文件相当于 pam_limits 模块的配置文件。
# vi /etc/pam.d/login
session required pam_limits.so
第二个问题: WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
原因分析:net.core.somaxconn 参数的值太小了。即全连接(即 accept 连接)的最大队列长度太小了。
解决方法:
# vi /etc/sysctl.conf
net.core.somaxconn = 511
# sysctl -p
查看方法:
# cat /proc/sys/net/core/somaxconn
# sysctl net.core.somaxconn
第三个问题:
WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
原因分析:vm.overcommit_memory 指的是进程申请的内存大小。当参数值为 0 时,如果一次性申请的内存大宽茄小超过了系统总内存,有可能被拒绝。当参数值为 0 时,有可能会导致 redis 执行 bgsave 操作保存 rdb 文件失败。(参考:)。
解决方法:
# vi /etc/sysctl.conf
vm.overcommit_memory = 1
# sysctl -p
查看方法:
# cat /proc/sys/vm/overcommit_memory
# sysctl vm.overcommit_memory
第四个问题:
WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
原因分析:Transparent Huge Pages (THP) 开启后会使 redis 时延变大和造成内存使用问题(参考:)。
解决方法(CentOS 6.X):
echo never /sys/kernel/mm/transparent_hugepage/enabled
# vim /etc/rc.local
echo never /sys/kernel/mm/transparent_hugepage/enabled
解决方法(CentOS 7.X):
# vim /etc/systemd/system/disable-transparent-huge-pages.service
[Unit]
Description=Disable Transparent Huge Pages (THP)
DefaultDependencies=no
After=sysinit.target local-fs.target
[Service]
Type=oneshot
ExecStart=/bin/sh -c 'echo never | tee /sys/kernel/mm/transparent_hugepage/enabled /dev/null'
[Install]
WantedBy=basic.target
# systemctl enable disable-transparent-huge-pages
# systemctl start disable-transparent-huge-pages
查看方法:
# cat /sys/kernel/mm/transparent_hugepage/enabled
always madvise [never]
redis是如何执行的
对于任何世雹一门技术,如果你只停留在「会用」的阶段,那就很难有所成就,甚至还有被裁员和找不到工作的风险,我相信能看此篇文章的你,一定是积极上进想有所作为的人,那么借此机会,我们来深入的解一下 Redis 的执搜橡帆行细节。
一条命令的执行过程有很多细节,但大体可分为:客户端先将用户输入的命令,转化为 Redis 相关的通讯协议,再用 socket 连接的方式将内容发送给服务器端,服务器端在接收到相关内容之后,先将内容转化为具体的执行命令,再判断用户授权信息和其他相关信息,当验证通过之后会执行最终命令,命令执行完之后,会进行相关的信息记录和数据统计,然后再把执行结果发送给客户端,这样一条命令的执行流程就结束了。如果是集群模式的话,主节点还会将命令同步至子节点,下面我们一起来看更加具体的执行流程。
步骤二:客户端先将命令转换成 Redis 协议,然后再通过 socket 连接发送给服务器端
客户端和服务器端是基于 socket 通信的,服务器端在初始化时会创建了一个 socket 监听,用于监测链接客户端的 socket 链接,源码如下:
当 socket 成功连接之后,客户端会先把命令转换成 Redis 通讯协议(RESP 协议,REdis Serialization Protocol)发送给服务器端,这个通信协议是为了保障服务器能最快速的理解命令的含义而制定的,如果没有这个通讯协议,那么 Redis 服务器端要遍历所有的空格以确认此条命令的含义,这样会加大服务器的运算量,而直接发送通讯协议,相当于把服务器端的解析工作交给了每一个客户端,这样会很大程度的提高 Redis 的运行速度。例如,当我们输入 set key val 命令时,客户端会把这个命令转换为 *3\r\n$3\r\nSET\r\n$4\r\nKEY\r\n$4\r\nVAL\r\n 协议发送给服务器端。 更多通讯协议,可访问官方文档:
扩展知识:I/O 多路复用
Redis 使用的是 I/O 多路复用功能来监听多 socket 链接的,这样就可以使用一个线程链接来处理多个请求,减少线程切换带来的开销,同时也避免了 I/O 阻塞操作,从而大大提高了 Redis 的运行效率。
综合来说,此步骤的执行流程如下:
步骤三:服务器端接收到命令
当数据大小验证通过之后,服务器端会对输入缓冲区中的请求命令进行分析,提取命令请求中包含的命令参数,存储在 client 对象(服务器端会为每个链接创建一个 Client 对象)的属性中。
步骤四:执行前准备
① 判断是否为退出命令,如果是则直接返回;
② 非 null 判断,检查 client 对象是否为 null,如果是返回错误信息;
③ 获取执行命令,根据 client 对象存储的属性信息去 redisCommand 结构中查询执行命令;
④ 用户权限效验,未通过身份验证的客户端只能执行 AUTH(授权) 命令,未通过身份验证的客户端执行了 AUTH 之外的命令如旦则返回错误信息;
⑤ 集群相关操作,如果是集群模式,把命令重定向到目标节点,如果是 master(主节点) 则不需要重定向;
⑥ 检查服务器端最大内存限制,如果服务器端开启了最大内存限制,会先检查内存大小,如果内存超过了最大值会对内存进行回收操作;
⑦ 持久化检测,检查服务器是否开启了持久化和持久化出错停止写入配置,如果开启了此配置并且有持久化失败的情况,禁止执行写命令;
⑧ 集群模式最少从节点(slave)验证,如果是集群模式并且配置了 repl min slaves to write(最小从节点写入),当从节点的数量少于配置项时,禁止执行写命令;
⑨ 只读从节点验证,当此服务器为只读从节点时,只接受 master 的写命令;
⑩ 客户端订阅判断,当客户端正在订阅频道时,只会执行部分命令(只会执行 SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUNSUBSCRIBE,其他命令都会被拒绝)。
⑪ 从节点状态效验,当服务器为 slave 并且没有连接 master 时,只会执行状态查询相关的命令,如 info 等;
⑫ 服务器初始化效验,当服务器正在启动时,只会执行 loading 标志的命令,其他的命令都会被拒绝;
⑬ lua 脚本阻塞效验,当服务器因为执行 lua 脚本阻塞时,只会执行部分命令;
⑭ 事务命令效验,如果执行的是事务命令,则开启事务把命令放入等待队列;
⑮ 监视器 (monitor) 判断,如果服务器打开了监视器功能,那么服务器也会把执行命令和相关参数发送给监视器 (监视器是用于监控服务器运行状态的)。
当服务器经过以上操作之后,就可以执行真正的操作命令了。
步骤五:执行最终命令,调用 redisCommand 中的 proc 函数执行命令。
步骤六:执行完后相关记录和统计 ① 检查慢查询是否开启,如果开启会记录慢查询日志; ② 检查统计信息是否开启,如果开启会记录一些统计信息,例如执行命令所耗费时长和计数器(calls)加1; ③ 检查持久化功能是否开启,如果开启则会记录持久化信息; ④ 如果有其它从服务器正在复制当前服务器,则会将刚刚执行的命令传播给其他从服务器。
步骤七:返回结果给客户端 命令执行完之后,服务器会通过 socket 的方式把执行结果发送给客户端,客户端再把结果展示给用户,至此一条命令的执行就结束了。
小结
当用户输入一条命令之后,客户端会以 socket 的方式把数据转换成 Redis 协议,并发送至服务器端,服务器端在接受到数据之后,会先将协议转换为真正的执行命令,在经过各种验证以保证命令能够正确并安全的执行,但验证处理完之后,会调用具体的方法执行此条命令,执行完成之后会进行相关的统计和记录,然后再把执行结果返回给客户端。
[img]bash:redis-server:command not found是什么情况
MySQL Error Message: Can not connect to MySQL server SQL: Error: Can't connect to MySQL server on 'localhost' (10061) Errno.: 2003 Click here to seek help. 这些是什么意思啊`? 有些网站打开就是这样`..前几天还可以打开的`,今天给我朋友上过后就这样了`.而且桌面上的宽带连接也不知道弄哪去了`. 我问过他,他说什么都没有弄啊`,,- - . 有没有谁知道山好姿怎么回事啊`.有些网站还是可以打开的`. 但是逗绝一部分就不行了`,前天还可以的,. 刚打开就出现这些袜敏英文字母. 谁懂该怎么弄吗 ?
关于rediscommand和rediscommand设计模式的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。