2021-09-09

Netapp传奇之WAFL文件系统以及RAID4

上次有朋友谈到这个话题,关于netapp与其改良型raid4,希望我能介绍这个东西,估计知道的人也不太多,我这里尽量用简单的语言来介绍一下他的特点,希望大家能看明白。

Netapp公司创建时间不算长,1992年才创建,但是netapp还是写下了一系列的神话,包括现在IBM的nas系统,都是OEM的netapp的产品。那么,netapp的优势在哪里呢?我在这里分析一下它的特点,WAFL与RAID4+。

WAFL文件系统是netapp自己设计的,运行在netapp专用操作系统DATA ONTAP上的一个文件系统,WAFL是“Write Anywhere File Layout”的意思,即“任意位置写入文件布局”的缩写。正因为有WAFL的这个特点,所以才有了RAID4+,一个改进型的raid4,使得没有校验瓶颈存在,而且能随意扩充硬盘的raid方式。

如果说传统的存储方式中,如果修改一个数据块,我们必须先定位到那个数据块,然后再修改,在我的前面写的raid5内部分析中,我们也看到了,如果修改一个单独的数据,我们必须先读出这个数据与校验,然后修改数据,计算校验,最后写入到同样的位置,这些特点,不仅仅是raid决定的,而且也是运行在raid之上的文件系统决定的。

在WAFL中,如果它也修改一个数据,他可能不管以前的数据的位置,直接把新数据与新校验写到新的位置,之后更改指针,告诉文件系统说,新的数据在这里,而不是原来那里了。这么做还有一个最大的好处就是,新的数据可能等到足够多以后,可以凑齐raid的一个条带以后,一起写进去,就可以大大的提高写的速度。

raid4+就在WAFL的配合下诞生了,传统的raid4是把所有的校验写在一块单独的硬盘上的,如果数据修改量很大,那么这个单独的硬盘就变成了性能瓶颈,而raid4+可以最大可能的把一个条带的数据,一次性的写入,所以,使得校验盘与其它的盘基本相当的写入量,而没有瓶颈出现。而且,当这个raid组想增加硬盘的时候,只是简单的放入新的硬盘即可,任意位置写的规则可以保证新的硬盘马上就被使用起来。

WAFL与raid4+为了尽量保证把数据合并后一次性写入,就必须依赖cache,在cache中才可以等到一定数量的数据之后再一起分批写入,而且,本身WAFL的日志也是记录在cache中的,也包括WAFL的inode的指针操作,也都是在cache中完成。所以,netapp也必须依赖电池或者ups对cache实施保护。

我们先看一个传统的raid4与改良型的raid4之间写的差别,如图,在传统型的raid4中,如果改写我如图的数据,每个数据需要读一次,校验盘可能会写6次,每个数据写一个,涉及到6个条带。但是,在改良型的raid4中,读已经不存在了,而且写的话,最小的可能性,只需要写2个条带,8个写io,一次性写入即可,至于指针,则由WAFL文件系统在cache中完成。

注意,这里为什么说最小可能写2个条带,因为写的时候还需要根据磁盘空间剩余情况,cache的利用情况来综合决定的,有可能也会涉及到3-4个条带,但是,可以肯定的是,算法尽量保证最少的磁盘写次数。

raid4+

我们上面分析了改良型的raid4的写,那么我们再分析一下它的raid组增加磁盘的过程,在一般的raid组中,想要给raid组增加一个磁盘,是非常困难的,因为数据以前就分布好了,除非再强行改变分布,但是,netapp不一样,它的文件系统本来就是任意写,所以很容易把新加的磁盘给用上。

add disk

那么说了这么多,netapp的WAFL与raid4+的优势已经很清楚了:

1、尽量保证数据一次性的写入,减少磁盘争用,提高写速度

2、因为任意写的特点,使得snapshot变得非常简单,而且,就算你不做snapshot,系统本身也一直在不停的产生snapshot,因为这样可以大大减少文件系统的恢复时间。

那么,有缺点吗?肯定有的,这个世界总是没有完美的东西存在的

1、因为任意写,为了保证每次都能操作一个条带,那么,系统希望尽量有充足的空闲空间,如使用率不要超过80%,否则,因为空闲空间太少而不能保证每次都写一个条带

2、因为任意写,可能会使本来连续的空间,分布在存储的任意位置,如数据库应用中,本来连续的表,在存储中多次修改以后,就不连续了,使得全表扫描或者备份变得很慢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用python中的pymsql完成如下:表结构与数据创建 1. 建立 `users` 表和 `orders` 表。 `users` 表有用户ID、用户名、年龄字段,(id,name,age) `orders` 表有订单ID、订单日期、订单金额,用户id字段。(id,order_date,amount,user_id) 2 两表的id作为主键,`orders` 表用户id为users的外键 3 插入数据 `users` (1, '张三', 18), (2, '李四', 20), (3, '王五', 22), (4, '赵六', 25), (5, '钱七', 28); `orders` (1, '2021-09-01', 500, 1), (2, '2021-09-02', 1000, 2), (3, '2021-09-03', 600, 3), (4, '2021-09-04', 800, 4), (5, '2021-09-05', 1500, 5), (6, '2021-09-06', 1200, 3), (7, '2021-09-07', 2000, 1), (8, '2021-09-08', 300, 2), (9, '2021-09-09', 700, 5), (10, '2021-09-10', 900, 4); 查询语句 1. 查询订单总金额 2. 查询所有用户的平均年龄,并将结果四舍五入保留两位小数。 3. 查询订单总数最多的用户的姓名和订单总数。 4. 查询所有不重复的年龄。 5. 查询订单日期在2021年9月1日至9月4日之间的订单总金额。 6. 查询年龄不大于25岁的用户的订单数量,并按照降序排序。 7. 查询订单总金额排名前3的用户的姓名和订单总金额。 8. 查询订单总金额最大的用户的姓名和订单总金额。 9. 查询订单总金额最小的用户的姓名和订单总金额。 10. 查询所有名字中含有“李”的用户,按照名字升序排序。 11. 查询所有年龄大于20岁的用户,按照年龄降序排序,并只显示前5条记录。 12. 查询每个用户的订单数量和订单总金额,并按照总金额降序排序。
06-03
这里是使用 Python 的 PyMySQL 完成上述任务的代码: ```python import pymysql # 连接数据库 conn = pymysql.connect(host='localhost', port=3306, user='root', password='123456', database='test') # 创建游标 cur = conn.cursor() # 创建 users 表 cur.execute(''' CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(20), age INT ) ''') # 创建 orders 表 cur.execute(''' CREATE TABLE orders ( id INT PRIMARY KEY, order_date DATE, amount INT, user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) ) ''') # 插入数据 users_data = [ (1, '张三', 18), (2, '李四', 20), (3, '王五', 22), (4, '赵六', 25), (5, '钱七', 28) ] orders_data = [ (1, '2021-09-01', 500, 1), (2, '2021-09-02', 1000, 2), (3, '2021-09-03', 600, 3), (4, '2021-09-04', 800, 4), (5, '2021-09-05', 1500, 5), (6, '2021-09-06', 1200, 3), (7, '2021-09-07', 2000, 1), (8, '2021-09-08', 300, 2), (9, '2021-09-09', 700, 5), (10, '2021-09-10', 900, 4) ] for user in users_data: cur.execute('INSERT INTO users VALUES (%s, %s, %s)', user) for order in orders_data: cur.execute('INSERT INTO orders VALUES (%s, %s, %s, %s)', order) # 提交事务 conn.commit() # 查询语句 # 1. 查询订单总金额 cur.execute('SELECT SUM(amount) FROM orders') print(cur.fetchone()[0]) # 2. 查询所有用户的平均年龄,并将结果四舍五入保留两位小数。 cur.execute('SELECT ROUND(AVG(age), 2) FROM users') print(cur.fetchone()[0]) # 3. 查询订单总数最多的用户的姓名和订单总数。 cur.execute(''' SELECT users.name, COUNT(*) AS total_orders FROM users JOIN orders ON users.id = orders.user_id GROUP BY users.id ORDER BY total_orders DESC LIMIT 1 ''') print(cur.fetchone()) # 4. 查询所有不重复的年龄。 cur.execute('SELECT DISTINCT age FROM users') print([row[0] for row in cur.fetchall()]) # 5. 查询订单日期在2021年9月1日至9月4日之间的订单总金额。 cur.execute('SELECT SUM(amount) FROM orders WHERE order_date BETWEEN "2021-09-01" AND "2021-09-04"') print(cur.fetchone()[0]) # 6. 查询年龄不大于25岁的用户的订单数量,并按照降序排序。 cur.execute(''' SELECT users.name, COUNT(*) AS total_orders FROM users JOIN orders ON users.id = orders.user_id WHERE age <= 25 GROUP BY users.id ORDER BY total_orders DESC ''') print(cur.fetchall()) # 7. 查询订单总金额排名前3的用户的姓名和订单总金额。 cur.execute(''' SELECT users.name, SUM(amount) AS total_amount FROM users JOIN orders ON users.id = orders.user_id GROUP BY users.id ORDER BY total_amount DESC LIMIT 3 ''') print(cur.fetchall()) # 8. 查询订单总金额最大的用户的姓名和订单总金额。 cur.execute(''' SELECT users.name, SUM(amount) AS total_amount FROM users JOIN orders ON users.id = orders.user_id GROUP BY users.id ORDER BY total_amount DESC LIMIT 1 ''') print(cur.fetchone()) # 9. 查询订单总金额最小的用户的姓名和订单总金额。 cur.execute(''' SELECT users.name, SUM(amount) AS total_amount FROM users JOIN orders ON users.id = orders.user_id GROUP BY users.id ORDER BY total_amount ASC LIMIT 1 ''') print(cur.fetchone()) # 10. 查询所有名字中含有“李”的用户,按照名字升序排序。 cur.execute('SELECT * FROM users WHERE name LIKE "%李%" ORDER BY name ASC') print(cur.fetchall()) # 11. 查询所有年龄大于20岁的用户,按照年龄降序排序,并只显示前5条记录。 cur.execute('SELECT * FROM users WHERE age > 20 ORDER BY age DESC LIMIT 5') print(cur.fetchall()) # 12. 查询每个用户的订单数量和订单总金额,并按照总金额降序排序。 cur.execute(''' SELECT users.name, COUNT(*) AS total_orders, SUM(amount) AS total_amount FROM users JOIN orders ON users.id = orders.user_id GROUP BY users.id ORDER BY total_amount DESC ''') print(cur.fetchall()) # 关闭游标和连接 cur.close() conn.close() ``` 注意:在运行代码之前,需要先安装 PyMySQL 模块,可以使用以下命令进行安装: ``` pip install pymysql ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值