存档

作者存档

自建用于bzz的geth(swap-endpoint)RPC(linux、windows详细部署步骤)

2021年6月7日 没有评论

最近由于以太坊很火,很多朋友需求自己架设自己的rpc服务。这里给出两个方案,一个是linux一个是win的。

初自建geth(endpoint)用于保证Swarm挖矿持续不中断为了更好的服务自己。为什么自建RPC?
自建geth的好处:
1、不受官方服务器限制、保证多节点24*7连接性;
2、自建geth没有任何限制,可以多节点共用一台;
3、bee0.6.x以上版本连接请求过快,官方免费rpc满足不了。

Linux推荐使用系统:Ubuntu18.04(centos要下载软件部署)
安装git

1
2
3
4
apt-get install software-properties-common -y
sudo add-apt-repository ppa:git-core/ppa -y
sudo apt-get update -y
sudo apt-get install git -y

查看是否安装成功

1
git --version

有显示版本号就是安装成功。
安装geth

1
2
3
4
sudo apt-get install software-properties-common -y
sudo add-apt-repository -y ppa:ethereum/ethereum
sudo apt-get update -y
sudo apt-get install ethereum -y

查看geth是否安装成功

1
geth --help

有信息反馈就是OK
安装screen让rpc在screen里面运行

1
apt-get install screen -y

创建一个叫geth的screen

1
screen -S geth

在screen里面运行启动命令

1
geth --cache=2048 --goerli --rpc --rpcaddr 0.0.0.0 --rpcport=8545 --rpcvhosts=* --rpcapi='eth,net,rpc'

等着他同步完成就可以了。
查看

1
screen -r geth

同步中的状态

Linux centos7/8
1. 下载go-ethereum

1
wget https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.10.3-991384a7.tar.gz

2. 解压 go-ethereum

1
tar -zxvf geth-linux-amd64-1.10.3-991384a7.tar.gz

3. 安装 go-ethereum

1
cp geth-linux-amd64-1.10.3-991384a7/geth /usr/bin/

三、运行go-ethereum

1. 启动一个名为geth的后台

1
screen -R geth

输入上面的命令后,按两次回车会新建一个后台。

2. 查看本机本地ip

1
ip address

3. 运行go-ethereum

1
geth --goerli --http --http.addr=1.1.1.1 --datadir /home/gethdata

#1.1.1.1换成自己ip
#–datadir /www/gethdata 指定存文件目录

注意: ip 需要使用第二步取得的ip取代

Ctrl+a+d退出 这玩意显示有点毛病

4. 检测go-ethereum 是否成功安装

1
lsof -i:8545

如果输出不为空,类似下图:

你已成功安装自己的go-ethereum 节点!不过还需要几个小时来等待它同步区块。

四、使用go-ethereum

在swarm节点上,更改配置文件的swap-endpoint字段:

swap-endpoint: http://1.1.1.1:8545 (1.1.1.1换成自己ip)
在你的SwarmBee的yaml配置文件里面修改好然后保存重启bee即可
如果你的Geth未同步完区块高度的话,则Bee会在Geth同步完后开始工作。

windows安装2012/2016/2019
这个就容易的多。直接去主网上下载。https://geth.ethereum.org/downloads/

1.下载https://geth.ethereum.org/downloads/
2.双击安装
3.geth.exe –goerli –http –http.addr=1.1.1.1 –datadir d:\gethdata
(自己建立一个放文件的gethdata)这个步骤不说明了。

利用Figlet工具创建酷炫VPS登入欢迎界面(转)

2021年5月3日 没有评论

有些时候我们在购买一些商家VPS服务器登入SSH后会看到商家自定义的欢迎界面,看着还感觉有点酷炫效果的。如果我们在自己管理和玩转的VPS、服务器中希望自定义比较个性的登入欢迎界面,可以利用Figlet工具进行设置,给我们闲暇且无聊的折腾过程一点点乐趣。

第一、Figlet工具的安装

wget ftp://ftp.figlet.org/pub/figlet/program/unix/figlet-2.2.5.tar.gz
cp figlet-2.2.5.tar.gz /usr/local/src/
cd /usr/local/src/
tar -zxvf figlet-2.2.5.tar.gz
cd figlet*
make figlet

因为我们需要生成需要的特定字符,所以需要在当前服务器中安装Figlet,默认没有安装包的,其实如果我们也只要在一台环境中安装,然后需要什么字符只要复制到需要的服务器中,并不需要所有都安装。同样的,我们也可以利用此生成的字符用到脚本运行的开始起头部分,用ECHO分行标注就可以。

这里需要补充一点,我们可能没有安装GCC,所以在执行make安装的时候会提示有”make: gcc: Command not found”错误,这里我们需要执行:

yum -y install gcc automake autoconf libtool make

常用的组件包。

Figlet工具的安装

如果没有错误,则会看到下面的成功安装界面。

Figlet工具的安装

第二、Figlet工具生成字符

./figlet LAOZUO.ORG -f fonts/standard.flf

这里我们需要用Figlet生成需要的字符,然后才可以用到我们的开机还原界面中。根据上述的脚本,换成我们自己的字符。以及我们可以用其他的字体。

字体:http://www.figlet.org/fontdb.cgi

Figlet工具生成字符

这里我用了一个3-d.flf字体的效果。具体我们可以根据不同的字体看看效果。这里老左就不多说了。

第三、添加登入欢迎界面

1、复制我们上面的字符

2、vi /etc/ssh/ssh-banner

添加到ssh-banner中。

3、设定Banner none

vi /etc/ssh/sshd_config

找到#Banner none一行,然后添加:

Banner /etc/ssh/ssh-banner

设定Banner none

然后保存退出。

4、重启SSH

/etc/init.d/sshd restart

最后,我们再退出当前SSH,然后重新登入。就可以看到这篇文章第一个图片的效果。Figlet生成字符然后添加登入界面完全是自己的折腾,看着登入界面和别人不同而已。

解决yum 出错:error: rpmdb: BDB0113 Thread/process 8173/139681223043136 failed: BDB1507

2021年4月6日 没有评论

s使用Ctrl+c 或者 Ctrl + z 或者 kill 或者其他原因 结束掉了yum进程,当再次执行yum的相关操作时报错:
错误:rpmdb: BDB0113 Thread/process 15381/140029102753600 failed: BDB1507 Thread died in Berkeley DB library
错误:db5 错误(-30973) 来自 dbenv->failchk:BDB0087 DB_RUNRECOVERY: Fatal error, run database recovery
错误:无法使用 db5 – (-30973) 打开 Packages 索引
错误:无法从 /var/lib/rpm 打开软件包数据库
CRITICAL:yum.main:

Error: rpmdb open failed

原因:rpm数据库在强制结束yum进程时被破坏了
解决办法:重新构建即可,步骤如下:
1、cd /var/lib/rpm
2、rm __db.* -rf #删除所有rpm库
3、rpm –rebuilddb #rpm的重新构建命令
4、yum clean all #用yum clean all清除
5、yum grouplist #用yum grouplist 命令测试yum,并进行相关更新

分类: Linux, 解决方案 标签: ,

win2008R2 sp1 update 错误80072EFE

2021年3月7日 没有评论

如果在检查更新时收bai到 Windows Update 错误 80072efe 或 80072f76,可能是因为计算机与 Windows Update 服务器之间的连接中断引起的。关闭 Windows Update,等待 10 到 15 分钟,然后再次运行 Windows Update。您也可以等待 Windows 自动更新在在其下一次计划时间时运行。 如果仍接收到这些错误之一,则可以运行自动疑难解答程序,该程序可以解决有关 Windows Update 的一些常见问题。 单击以下按钮: 解决此问题 在“文件下载”对话框中,单击“运行”,然后按照向导中的步骤进行操作。下载地址:

https://docs.microsoft.com/zh-cn/troubleshoot/windows-client/deployment/update-windows-update-agent#automatically-download-windows-update-agent

原始产品版本: Windows 10 – 所有版本,Windows Server 2012
原始 KB 编号: 949104

命令行程序哈希值查询方法(适用于Win8及以上系统)

2021年3月4日 没有评论

【哈希值查询方法(适用于Win8及以上系统)】
在命令提示符中输入:
certutil -hashfile “在此输入文件路径” SHA256
certutil -hashfile “在此输入文件路径” SHA1
certutil -hashfile “在此输入文件路径” MD5

IIS7/8如何实现访问HTTP跳转到HTTPS访问

2021年2月7日 没有评论

在URL中新建规则

1.新建一个空白规则,让http的访问跳转到https上

2.起一个名字例如HTTP to HTTPS redirect

3.在操作条件设置中选择重定向:https://{HTTP_HOST}/{R:1}
重定向类型:已找到(302) 或 参阅其它(303) 注:默认301也是可以的。

ps:
排除问题,今天,安装完iis重写后,设定强制301从http跳转https时出现进程池自动死的问题。其实是版本不同。访问出现:

Service Unavailable
HTTP Error 503. The service is unavailable.

看了日志后发现以下问题提示: C:\WINDOWS\system32\inetsrv\rewrite.dll 未能加载。返回的数据为错误。
先全部删除重写组件和web平台组件服务。然后重新下载安装即可。

解决:
不要用Web平台组件去下载URL重写工具, 自己手动下载, Url Rewrite 2.0 https://www.microsoft.com/zh-cn/download/details.aspx?id=7435
IIS7和IIS8的依旧可以用。

分类: 网络产品, 解决方案 标签:

linux centos7清除系统日志历史记录登录信息

2021年2月1日 没有评论

平时不管是web还是系统产生的日志都可能导致洗盘爆满,所以我在这里分享一些基本常用清理linux日志的方法。

# echo > /var/log/wtmp //清除用户登录记录
# echo > /var/log/btmp //清除尝试登录记录
# echo>/var/log/lastlog //清除最近登录信息
# echo > /var/log/secure //登录信息
# echo > /var/log/messages
# echo>/var/log/syslog //记录系统日志的服务
# echo>/var/log/xferlog
# echo>/var/log/auth.log
# echo>/var/log/user.log
# cat /dev/null > /var/adm/sylog
# cat /dev/null > /var/log/maillog
# cat /dev/null > /var/log/openwebmail.log
# cat /dev/null > /var/log/mail.info
# echo>/var/run/utmp
清除操作过的命令记录

# echo > .bash_history //清除保存的用户操作历史记录
# history -cw //清除所有历史

Linux查看History记录加时间戳小技巧
熟悉bash的都一定知道使用history可以输出你曾经输入过的历史命令,例如
[root@servyou_web ~]# history | more
./test.sh
vim test.sh
./test.sh
但是这里只显示了命令,并没有显示执行命令的时间,因为保存历史命令的~/.bash_history里并没有保存时间。

通过设置环境变量 export HISTTIMEFORMAT=”%F %T whoami ” 给history加上时间戳

[root@servyou_web ~]# export HISTTIMEFORMAT=”%F %T whoami ”
[root@servyou_web ~]# history | tail
2011-06-22 19:17:29 root 15 2011-06-22 19:13:02 root ./test.sh
2011-06-22 19:17:29 root 16 2011-06-22 19:13:02 root vim test.sh
2011-06-22 19:17:29 root 17 2011-06-22 19:13:02 root ./test.sh
2011-06-22 19:17:29 root 18 2011-06-22 19:13:02 root vim test.sh
2011-06-22 19:17:29 root 19 2011-06-22 19:13:02 root ./test.sh
2011-06-22 19:17:29 root 20 2011-06-22 19:13:02 root vim test.sh
2011-06-22 19:17:29 root 21 2011-06-22 19:13:02 root ./test.sh
2011-06-22 19:17:29 root 22 2011-06-22 19:13:02 root vim test.sh
2011-06-22 19:25:22 root 22 2011-06-22 19:13:02 root vim test.sh
2011-06-22 19:25:28 root history | tail

可以看到,历史命令的时间戳已经加上了,但是.bash_history里并没有加上这个时间戳。其实这个时间记录是保存在当前shell进程内存里的,如果你logout并且重新登录的话会发现你上次登录时执行的那些命令的时间戳都为同一个值,即当时logout时的时间。

尽管如此,对于加上screen的bash来说,这个时间戳仍然可以长时间有效的,毕竟只要你的server不重启,screen就不会退出,因而这些时间就能长时间保留。你也可以使用echo ‘export HISTTIMEFORMAT=”%F %T whoami “‘ >> /etc/profile 然后source一下就OK

例二: vi /root/.bash_history

例三:

 1、修改/etc/profile将HISTSIZE=1000改成0或1

  清除用户home路径下。bash_history

  2、立即清空里的history当前历史命令的记录

  history -c

  3、bash执行命令时不是马上把命令名称写入history文件的,而是存放在内部的buffer中,等bash退出时会一并写入。

  不过,可以调用’history -w’命令要求bash立即更新history文件。

  history -w

如何将CentOS 7升级到CentOS 8

2021年1月9日 没有评论

在本文中,您将学习如何将CentOS 7升级到CentOS 8。本文描述的步骤尚未描述正式升级,因此不能应用于生产服务器。
Upgrade-CentOS-7-to-CentOS-8

步骤1:安装EPEL储存库

首先,通过运行以下命令安装EPL存储库

yum install epel-release -y

在CentOS 7中安装EPEL Repo

步骤2:安装yum-utils工具

成功安装EPEL之后,通过运行以下命令来安装yum-utils。

然后,您需要通过执行命令来解析RPM软件包。

yum install rpmconf
rpmconf -a

保留默认RPM设置

接下来,清理所有不需要的软件包。

package-cleanup –leaves
package-cleanup –orphans

清理RPM软件包

步骤3:在CentOS 7中安装dnf

现在安装dnf软件包管理器,它是CentOS 8的默认软件包管理器。

yum install dnf

在CentOS 7中安装dnf

您还需要使用以下命令删除yum软件包管理器。

dnf -y remove yum yum-metadata-parser
rm -Rf /etc/yum

在CentOS 7中删除Yum

步骤4:将CentOS 7升级到CentOS 8

dnf upgrade

升级CentOS 7

接下来,如下所示使用dnf安装CentOS 8发行包。这需要一段时间。

dnf -y upgrade http://mirror.bytemark.co.uk/centos/8/BaseOS/x86_64/os/Packages/centos-release-8.0-0.1905.0.9.el8.x86_64.rpm

安装CentOS 8版本

接下来,升级EPEL存储库。

dnf -y upgrade https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm

升级EPEL存储库

成功升级EPEL存储库后,请删除所有临时文件。

dnf clean all
使用nodeps参数删除CentOS 7的旧内核。

rpm -e `rpm -q kernel` –nodeps
接下来,请确保删除有冲突的软件包。

rpm -e –nodeps sysvinit-tools
此后,启动CentOS 8系统升级,如下所示。

dnf -y –releasever=8 –allowerasing –setopt=deltarpm=false distro-sync

CentOS 8系统升级

如果升级发现有报错,需要卸载from package后面的报名:

rpm -e –nodeps sysvinit-tools-2.88-14.dsf.el7.x86_64
rpm -e –nodeps python-inotify-0.9.4-4.el7.noarch
rpm -e –nodeps adwaita-qt5-1.0-1.el7.x86_64
rpm -e –nodeps pycairo-1.8.10-8.el7.x86_64
然后再次执行升级,此步骤需要等待较长时间。

dnf -y –releasever=8 –allowerasing –setopt=deltarpm=false distro-sync
步骤5:为CentOS 8安装新内核

要为CentOS 8安装新的内核,请运行命令。

dnf -y install kernel-core

在CentOS 8中安装内核

最后,安装CentOS 8最小软件包。

dnf -y groupupdate “Core” “Minimal Install”
现在,您可以通过以下命令运行检查安装的CentOS版本。

cat /etc/redhat-release
检查CentOS版本

升级完系统,记得重启,以上是将CentOS 7升级到CentOS 8的步骤,升级之前请做好数据备份,升级会造成一部分应用被卸载;大家可以学习借鉴之,还有其他的升级方法。

Linux 运维需要掌握的 17 个实用技巧(转)

2020年12月1日 没有评论

1、查找当前目录下所有以.tar结尾的文件然后移动到指定目录:

find . -name “*.tar” -exec mv {}./backup/ ;

注解:find –name 主要用于查找某个文件名字,-exec 、xargs可以用来承接前面的结果,然后将要执行的动作,一般跟find在一起用的很多,find使用我们可以延伸-mtime查找修改时间、-type是指定对象类型(常见包括f代表文件、d代表目录),-size 指定大小,例如经常用到的:查找当前目录30天以前大于100M的LOG文件并删除。
find . -name “*.log” –mtime +30 –typef –size +100M |xargs rm –rf {};
2、批量解压当前目录下以.zip结尾的所有文件到指定目录:

for i in `find . –name “*.zip”–type f `

do

unzip –d $i /data/www/img/

done
注解:forI in (command);do … done为for循环的一个常用格式,其中I为变量,可以自己指定。

3、sed常用命收集:test.txt做测试

如何去掉行首的.字符:

sed-i ‘s/^.//g’ test.txt

在行首添加一个a字符:

sed’s/^/a/g’ test.txt

在行尾添加一个a字符:

sed’s/$/a/‘ tets.txt

在特定行后添加一个c字符:

sed ‘/wuguangke/ac’ test.txt

在行前加入一个c字符:

sed’/wuguangke/ic’ test.txt
更多sed命令请查阅相关文档。

4、如何判断某个目录是否存在,不存在则新建,存在则打印信息。

if

[! –d /data/backup/];then

Mkdir–p /data/backup/

else

echo “The Directory alreadyexists,please exit”

fi
注解:if…;then …else ..fi:为if条件语句,!叹号表示反义“不存在“,-d代表目录。

5、监控linux磁盘根分区,如果根分区空间大于等于90%,发送邮件给Linux SA

(1)、打印根分区大小

df -h |sed -n ‘//$/p’|awk ‘{print $5}’|awk –F ”%” ‘{print $1}’
注解:awk ‘{print $5}’意思是打印第5个域,-F的意思为分隔,例如以%分隔,简单意思就是去掉百分号,awk –F. ‘{print $1}’分隔点.号。

(2)、if条件判断该大小是否大于90,如果大于90则发送邮件报警

while sleep 5m

do

for i in `df -h |sed -n ‘//$/p’ |awk ‘{print $5}’ |sed ‘s/%//g’`

do

echo $i

if [ $i -ge 90 ];then

echo “More than 90% Linux of disk space ,Please LinuxSA Check Linux Disk !” |mail -s “Warn Linux / Parts is $i%”

XXX@XXX.XX

fi

done

done
6、统计 Nginx 访问日志,访问量排在前20 的 ip地址:

cat access.log |awk ‘{print $1}’|sort|uniq -c |sort -nr |head -20
注解:sort排序、uniq(检查及删除文本文件中重复出现的行列 )

7、sed另外一个用法找到当前行,然后在修改该行后面的参数:

sed -i ‘/SELINUX/s/enforcing/disabled/’ /etc/selinux/config
Sed冒号方式 sed -i ‘s:/tmp:/tmp/abc/:g’test.txt意思是将/tmp改成/tmp/abc/。

8、打印出一个文件里面最大和最小值:

cat a.txt |sort -nr|awk ‘{}END{print} NR==1′

cat a.txt |sort -nr |awk ‘END{print} NR==1′
这个才是真正的打印最大最小值:sed ‘s/ / /g’ a.txt |sort -nr|sed -n ’1p;$p’

9、使用snmpd抓取版本为v2的cacti数据方式:

snmpwalk -v2c -c public 192.168.0.241
10、修改文本中以jk结尾的替换成yz:

sed -e ‘s/jk$/yz/g’ b.txt
11、网络抓包:tcpdump

tcpdump -nn host 192.168.56.7 and port 80 抓取56.7通过80请求的数据包。

tcpdump -nn host 192.168.56.7 or ! host 192.168.0.22 and port 80 排除0.22 80端口!

tcp/ip 7层协议物理层–数据链路层-网络层-传输层-会话层-表示层-应用层。
12、显示最常用的20条命令:

cat .bash_history |grep -v ^# |awk ‘{print $1}’ |sort |uniq -c |sort -nr |head-20
13、写一个脚本查找最后创建时间是3天前,后缀是*.log的文件并删除。

find . -mtime +3 -name “*.log” |xargs rm -rf {} ;
14、写一个脚本将某目录下大于100k的文件移动至/tmp下。

find . -size +100k -exec mv {} /tmp ;
15、写一个防火墙配置脚本,只允许远程主机访问本机的80端口。

iptables -F

iptables -X

iptables -A INPUT -p tcp –dport 80 -j accept

iptables -A INPUT -p tcp -j REJECT
或者
iptables -A INPUT -m state –state NEW-m tcp -p tcp –dport 80 -j ACCEPT
16、写一个脚本进行nginx日志统计,得到访问ip最多的前10个(nginx日志路径:

/home/logs/nginx/default/access.log)。

cd /home/logs.nginx/default

sort -m -k 4 -o access.logok access.1 access.2 access.3 …..

cat access.logok |awk ‘{print $1}’|sort -n|uniq -c|sort -nr |head -10
17.替换文件中的目录
sed ‘s:/user/local:/tmp:g’ test.txt
或者

sed -i ‘s//usr/local//tmp/g’ test.txt

Redis 为什么变慢了?一文教你定位与排查分析

2020年11月4日 没有评论

Redis 作为内存数据库,拥有非常高的性能,单个实例的QPS能够达到10W左右。但我们在使用Redis时,经常时不时会出现访问延迟很大的情况,如果你不知道 Redis 的内部实现原理,在排查问题时就会一头雾水。
很多时候,Redis 出现访问延迟变大,都与我们的使用不当或运维不合理导致的。
这篇文章我们就来分析一下 Redis 在使用过程中,经常会遇到的延迟问题以及如何定位和分析。
使用复杂度高的命令
如果在使用Redis时,发现访问延迟突然增大,如何进行排查?
首先,第一步,建议你去查看一下Redis的慢日志。Redis提供了慢日志命令的统计功能,我们通过以下设置,就可以查看有哪些命令在执行时延迟比较大。
首先设置Redis的慢日志阈值,只有超过阈值的命令才会被记录,这里的单位是微妙,例如设置慢日志的阈值为5毫秒,同时设置只保留最近1000条慢日志记录:
# 命令执行超过5毫秒记录慢日志
CONFIG SET slowlog-log-slower-than 5000
# 只保留最近1000条慢日志
CONFIG SET slowlog-max-len 1000
设置完成之后,所有执行的命令如果延迟大于5毫秒,都会被Redis记录下来,我们执行SLOWLOG get 5查询最近5条慢日志:
127.0.0.1:6379> SLOWLOG get 5
1) 1) (integer) 32693 # 慢日志ID
2) (integer) 1593763337 # 执行时间
3) (integer) 5299 # 执行耗时(微妙)
4) 1) “LRANGE” # 具体执行的命令和参数
2) “user_list_2000″
3) “0″
4) “-1″
2) 1) (integer) 32692
2) (integer) 1593763337
3) (integer) 5044
4) 1) “GET”
2) “book_price_1000″

通过查看慢日志记录,我们就可以知道在什么时间执行哪些命令比较耗时,如果你的业务经常使用O(N)以上复杂度的命令,例如sort、sunion、zunionstore,或者在执行O(N)命令时操作的数据量比较大,这些情况下Redis处理数据时就会很耗时。
如果你的服务请求量并不大,但Redis实例的CPU使用率很高,很有可能是使用了复杂度高的命令导致的。
解决方案就是,不使用这些复杂度较高的命令,并且一次不要获取太多的数据,每次尽量操作少量的数据,让Redis可以及时处理返回。
存储 bigkey
如果查询慢日志发现,并不是复杂度较高的命令导致的,例如都是SET、DELETE操作出现在慢日志记录中,那么你就要怀疑是否存在Redis写入了bigkey的情况。
Redis在写入数据时,需要为新的数据分配内存,当从Redis中删除数据时,它会释放对应的内存空间。
如果一个key写入的数据非常大,Redis在分配内存时也会比较耗时。同样的,当删除这个key的数据时,释放内存也会耗时比较久。
你需要检查你的业务代码,是否存在写入bigkey的情况,需要评估写入数据量的大小,业务层应该避免一个key存入过大的数据量。
那么有没有什么办法可以扫描现在Redis中是否存在bigkey的数据吗?
Redis也提供了扫描bigkey的方法:
redis-cli -h $host -p $port –bigkeys -i 0.01
使用上面的命令就可以扫描出整个实例key大小的分布情况,它是以类型维度来展示的。
需要注意的是当我们在线上实例进行bigkey扫描时,Redis的QPS会突增,为了降低扫描过程中对Redis的影响,我们需要控制扫描的频率,使用-i参数控制即可,它表示扫描过程中每次扫描的时间间隔,单位是秒。
使用这个命令的原理,其实就是Redis在内部执行scan命令,遍历所有key,然后针对不同类型的key执行strlen、llen、hlen、scard、zcard来获取字符串的长度以及容器类型(list/dict/set/zset)的元素个数。
而对于容器类型的key,只能扫描出元素最多的key,但元素最多的key不一定占用内存最多,这一点需要我们注意下。不过使用这个命令一般我们是可以对整个实例中key的分布情况有比较清晰的了解。
针对 bigkey 的问题,Redis官方在4.0版本推出了lazy-free的机制,用于异步释放bigkey的内存,降低对Redis性能的影响。即使这样,我们也不建议使用bigkey,bigkey 在集群的迁移过程中,也会影响到迁移的性能,这个后面在介绍集群相关的文章时,会再详细介绍到。
集中过期
有时你会发现,平时在使用Redis时没有延时比较大的情况,但在某个时间点突然出现一波延时,而且报慢的时间点很有规律,例如某个整点,或者间隔多久就会发生一次。
如果出现这种情况,就需要考虑是否存在大量key集中过期的情况。
如果有大量的key在某个固定时间点集中过期,在这个时间点访问Redis时,就有可能导致延迟增加。
Redis 的过期策略采用主动过期+懒惰过期两种策略:
主动过期:Redis内部维护一个定时任务,默认每隔100毫秒会从过期字典中随机取出20个key,删除过期的key,如果过期key的比例超过了25%,则继续获取20个key,删除过期的key,循环往复,直到过期key的比例下降到25%或者这次任务的执行耗时超过了25毫秒,才会退出循环
懒惰过期:只有当访问某个key时,才判断这个key是否已过期,如果已经过期,则从实例中删除
注意,Redis的主动过期的定时任务,也是在Redis主线程中执行的,也就是说如果在执行主动过期的过程中,出现了需要大量删除过期key的情况,那么在业务访问时,必须等这个过期任务执行结束,才可以处理业务请求。此时就会出现,业务访问延时增大的问题,最大延迟为25毫秒。
而且这个访问延迟的情况,不会记录在慢日志里。慢日志中只记录真正执行某个命令的耗时,Redis主动过期策略执行在操作命令之前,如果操作命令耗时达不到慢日志阈值,它是不会计算在慢日志统计中的,但我们的业务却感到了延迟增大。
此时你需要检查你的业务,是否真的存在集中过期的代码,一般集中过期使用的命令是expireat或pexpireat命令,在代码中搜索这个关键字就可以了。
如果你的业务确实需要集中过期掉某些key,又不想导致Redis发生抖动,有什么优化方案?
解决方案是,在集中过期时增加一个随机时间,把这些需要过期的key的时间打散即可。
伪代码可以这么写:
这样 Redis 在处理过期时,不会因为集中删除key导致压力过大,阻塞主线程。
另外,除了业务使用需要注意此问题之外,还可以通过运维手段来及时发现这种情况。
做法是我们需要把Redis的各项运行数据监控起来,执行info可以拿到所有的运行数据,在这里我们需要重点关注expired_keys这一项,它代表整个实例到目前为止,累计删除过期key的数量。
我们需要对这个指标监控,当在很短时间内这个指标出现突增时,需要及时报警出来,然后与业务报慢的时间点对比分析,确认时间是否一致,如果一致,则可以认为确实是因为这个原因导致的延迟增大。
实例内存达到上限
有时我们把 Redis 当做纯缓存使用,就会给实例设置一个内存上限maxmemory,然后开启LRU淘汰策略。
当实例的内存达到了 maxmemory 后,你会发现之后的每次写入新的数据,有可能变慢了。
导致变慢的原因是,当Redis内存达到maxmemory后,每次写入新的数据之前,必须先踢出一部分数据,让内存维持在maxmemory之下。
这个踢出旧数据的逻辑也是需要消耗时间的,而具体耗时的长短,要取决于配置的淘汰策略:
allkeys-lru:不管key是否设置了过期,淘汰最近最少访问的key
volatile-lru:只淘汰最近最少访问并设置过期的key
allkeys-random:不管key是否设置了过期,随机淘汰
volatile-random:只随机淘汰有设置过期的key
allkeys-ttl:不管key是否设置了过期,淘汰即将过期的key
noeviction:不淘汰任何key,满容后再写入直接报错
allkeys-lfu:不管key是否设置了过期,淘汰访问频率最低的key(4.0+支持)
volatile-lfu:只淘汰访问频率最低的过期key(4.0+支持)
具体使用哪种策略,需要根据业务场景来决定。
我们最常使用的一般是 allkeys-lru或volatile-lru策略,它们的处理逻辑是,每次从实例中随机取出一批key(可配置),然后淘汰一个最少访问的key,之后把剩下的key暂存到一个池子中,继续随机取出一批key,并与之前池子中的key比较,再淘汰一个最少访问的key。以此循环,直到内存降到maxmemory之下。
如果使用的是allkeys-random或volatile-random策略,那么就会快很多,因为是随机淘汰,那么就少了比较key访问频率时间的消耗了,随机拿出一批key后直接淘汰即可,因此这个策略要比上面的LRU策略执行快一些。
但以上这些逻辑都是在访问Redis时,真正命令执行之前执行的,也就是它会影响我们访问Redis时执行的命令。
另外,如果此时Redis实例中有存储bigkey,那么在淘汰bigkey释放内存时,这个耗时会更加久,延迟更大,这需要我们格外注意。
如果你的业务访问量非常大,并且必须设置 maxmemory 限制实例的内存上限,同时面临淘汰key导致延迟增大的的情况,要想缓解这种情况,除了上面说的避免存储bigkey、使用随机淘汰策略之外,也可以考虑拆分实例的方法来缓解,拆分实例可以把一个实例淘汰key的压力分摊到多个实例上,可以在一定程度降低延迟。
fork 耗时严重
如果你的Redis开启了自动生成RDB和AOF重写功能,那么有可能在后台生成RDB和AOF重写时导致Redis的访问延迟增大,而等这些任务执行完毕后,延迟情况消失。
遇到这种情况,一般就是执行生成RDB和AOF重写任务导致的。
生成RDB和AOF都需要父进程fork出一个子进程进行数据的持久化,在fork执行过程中,父进程需要拷贝内存页表给子进程,如果整个实例内存占用很大,那么需要拷贝的内存页表会比较耗时,此过程会消耗大量的CPU资源,在完成fork之前,整个实例会被阻塞住,无法处理任何请求,如果此时CPU资源紧张,那么fork的时间会更长,甚至达到秒级。这会严重影响Redis的性能。
具体原理也可以参考我之前写的文章:Redis持久化是如何做的?RDB和AOF对比分析。
我们可以执行info命令,查看最后一次fork执行的耗时latest_fork_usec,单位微妙。这个时间就是整个实例阻塞无法处理请求的时间。
除了因为备份的原因生成RDB之外,在主从节点第一次建立数据同步时,主节点也会生成RDB文件给从节点进行一次全量同步,这时也会对Redis产生性能影响。
要想避免这种情况,我们需要规划好数据备份的周期,建议在从节点上执行备份,而且最好放在低峰期执行。如果对于丢失数据不敏感的业务,那么不建议开启AOF和AOF重写功能。
另外,fork的耗时也与系统有关,如果把Redis部署在虚拟机上,那么这个时间也会增大。所以使用Redis时建议部署在物理机上,降低fork的影响。
绑定 CPU
很多时候,我们在部署服务时,为了提高性能,降低程序在使用多个CPU时上下文切换的性能损耗,一般会采用进程绑定CPU的操作。
但在使用Redis时,我们不建议这么干,原因如下。
绑定CPU的Redis,在进行数据持久化时,fork出的子进程,子进程会继承父进程的CPU使用偏好,而此时子进程会消耗大量的CPU资源进行数据持久化,子进程会与主进程发生CPU争抢,这也会导致主进程的CPU资源不足访问延迟增大。
所以在部署 Redis 进程时,如果需要开启RDB和AOF重写机制,一定不能进行CPU绑定操作!
AOF配合不合理
上面提到了,当执行AOF文件重写时会因为fork执行耗时导致Redis延迟增大,除了这个之外,如果开启AOF机制,设置的策略不合理,也会导致性能问题。
开启AOF后,Redis会把写入的命令实时写入到文件中,但写入文件的过程是先写入内存,等内存中的数据超过一定阈值或达到一定时间后,内存中的内容才会被真正写入到磁盘中。
AOF为了保证文件写入磁盘的安全性,提供了3种刷盘机制:
appendfsync always:每次写入都刷盘,对性能影响最大,占用磁盘IO比较高,数据安全性最高
appendfsync everysec:1秒刷一次盘,对性能影响相对较小,节点宕机时最多丢失1秒的数据
appendfsync no:按照操作系统的机制刷盘,对性能影响最小,数据安全性低,节点宕机丢失数据取决于操作系统刷盘机制
当使用第一种机制appendfsync always时,Redis每处理一次写命令,都会把这个命令写入磁盘,而且这个操作是在主线程中执行的。
内存中的的数据写入磁盘,这个会加重磁盘的IO负担,操作磁盘成本要比操作内存的代价大得多。如果写入量很大,那么每次更新都会写入磁盘,此时机器的磁盘IO就会非常高,拖慢Redis的性能,因此我们不建议使用这种机制。

与第一种机制对比,appendfsync everysec会每隔1秒刷盘,而appendfsync no取决于操作系统的刷盘时间,安全性不高。因此我们推荐使用appendfsync everysec这种方式,在最坏的情况下,只会丢失1秒的数据,但它能保持较好的访问性能。

当然,对于有些业务场景,对丢失数据并不敏感,也可以不开启AOF。

使用 Swap
如果你发现Redis突然变得非常慢,每次访问的耗时都达到了几百毫秒甚至秒级,那此时就检查Redis是否使用到了Swap,这种情况下Redis基本上已经无法提供高性能的服务。

我们知道,操作系统提供了Swap机制,目的是为了当内存不足时,可以把一部分内存中的数据换到磁盘上,以达到对内存使用的缓冲。

但当内存中的数据被换到磁盘上后,访问这些数据就需要从磁盘中读取,这个速度要比内存慢太多!

尤其是针对Redis这种高性能的内存数据库来说,如果Redis中的内存被换到磁盘上,对于Redis这种性能极其敏感的数据库,这个操作时间是无法接受的。

我们需要检查机器的内存使用情况,确认是否确实是因为内存不足导致使用到了Swap。

如果确实使用到了Swap,要及时整理内存空间,释放出足够的内存供Redis使用,然后释放Redis的Swap,让Redis重新使用内存。

释放Redis的Swap过程通常要重启实例,为了避免重启实例对业务的影响,一般先进行主从切换,然后释放旧主节点的Swap,重新启动服务,待数据同步完成后,再切换回主节点即可。

可见,当Redis使用到Swap后,此时的Redis的高性能基本被废掉,所以我们需要提前预防这种情况。

我们需要对Redis机器的内存和Swap使用情况进行监控,在内存不足和使用到Swap时及时报警出来,及时进行相应的处理。

网卡负载过高
如果以上产生性能问题的场景,你都规避掉了,而且Redis也稳定运行了很长时间,但在某个时间点之后开始,访问Redis开始变慢了,而且一直持续到现在,这种情况是什么原因导致的?
之前我们就遇到这种问题,特点就是从某个时间点之后就开始变慢,并且一直持续。这时你需要检查一下机器的网卡流量,是否存在网卡流量被跑满的情况。
网卡负载过高,在网络层和TCP层就会出现数据发送延迟、数据丢包等情况。Redis的高性能除了内存之外,就在于网络IO,请求量突增会导致网卡负载变高。
如果出现这种情况,你需要排查这个机器上的哪个Redis实例的流量过大占满了网络带宽,然后确认流量突增是否属于业务正常情况,如果属于那就需要及时扩容或迁移实例,避免这个机器的其他实例受到影响。
运维层面,我们需要对机器的各项指标增加监控,包括网络流量,在达到阈值时提前报警,及时与业务确认并扩容。
总结
以上我们总结了Redis中常见的可能导致延迟增大甚至阻塞的场景,这其中既涉及到了业务的使用问题,也涉及到Redis的运维问题。
可见,要想保证Redis高性能的运行,其中涉及到CPU、内存、网络,甚至磁盘的方方面面,其中还包括操作系统的相关特性的使用。
作为开发人员,我们需要了解Redis的运行机制,例如各个命令的执行时间复杂度、数据过期策略、数据淘汰策略等,使用合理的命令,并结合业务场景进行优化。
作为DBA运维人员,需要了解数据持久化、操作系统fork原理、Swap机制等,并对Redis的容量进行合理规划,预留足够的机器资源,对机器做好完善的监控,才能保证Redis的稳定运行。

分类: Linux 标签: