Redis简介要义
Redis运行在内存中但是可以持久化到磁盘, 重启的时候可以再次加载进行使用
Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行
Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作
Redis支持数据的备份,即master-slave模式的数据备份
Redis数据类型
Redis的数据类型很重要, 这是他做很多事情的基础, 不理解的话很难用好
. . .
例如 :#!/usr/bin/python
# -*- coding: UTF-8 -*-
list = [ 'runoob', 786 , 2.23, 'john', 70.2 ]
tinylist = [123, 'john']
print list # 输出完整列表
print list[0] # 输出列表的第一个元素
print list[1:3] # 输出第二个至第三个的元素
print list[2:] # 输出从第三个开始至列表末尾的所有元素
print tinylist * 2 # 输出列表两次
print list + tinylist # 打印组合的列表
以上实例输出结果:['runoob', 786, 2.23, 'john', 70.2]
runoob
[786, 2.23]
[2.23, 'john', 70.2]
[123, 'john', 123, 'john']
['runoob', 786, 2.23, 'john', 70.2, 123, 'john']
tuple = ( 'runoob', 786 , 2.23, 'john', 70.2 )
, 除了元祖用()而list用[], 而且元祖只是可读的, 其他的跟list一毛一样
#!/usr/bin/python |
输出结果为:This is one
This is two
{'dept': 'sales', 'code': 6734, 'name': 'john'}
['dept', 'code', 'name']
['sales', 6734, 'john']
变量在使用前,必须在代码中进行声明,即创建该变量。
编译程序执行代码之前编译器需要知道如何给语句变量开辟存储区,用于存储变量的值。
Lua 变量有三种类型:全局变量、局部变量、表中的域。
Lua 中的变量全是全局变量,那怕是语句块或是函数里,除非用 local 显式声明为局部变量。
局部变量的作用域为从声明位置开始到所在语句块结束。
变量的默认值均为 nil。
a = 5 -- 全局变量 |
执行以上实例输出结果为:
$ lua test.lua |
在 Lua 里,table 的创建是通过”构造表达式”来完成,
最简单构造表达式是{},用来创建一个空表。
也可以在表里添加一些数据,直接初始化表:-- 创建一个空的 table
local tbl1 = {}
-- 直接初始表
local tbl2 = {"apple", "pear", "orange", "grape"}
Lua 中的表(table)其实是一个”关联数组”(associative arrays),数组的索引可以是数字或者是字符串。
-- table_test.lua 脚本文件 |
脚本执行结果为:$ lua table_test.lua
key : value
10 : 33
不同于其他语言的数组把 0 作为数组的初始索引,在 Lua 里表的默认初始索引一般以 1 开始。-- table_test2.lua 脚本文件
local tbl = {"apple", "pear", "orange", "grape"}
for key, val in pairs(tbl) do
print("Key", key)
end
脚本执行结果为:$ lua table_test2.lua
Key 1
Key 2
Key 3
Key 4
table 不会固定长度大小,有新数据添加时 table 长度会自动增长,没初始的 table 都是 nil。-- table_test3.lua 脚本文件
a3 = {}
for i = 1, 10 do
a3[i] = i
end
a3["key"] = "val"
print(a3["key"])
print(a3["none"])
脚本执行结果为:$ lua table_test3.lua
val
nil
epoll API是Linux系统专有的,在2.6版中新增。
epoll API的核心数据结构称作epoll实例,它和一个打开的文件描述符相关联。这个文件
描述符不是用来做I/O操作的,相反,它是内核数据结构的句柄,这些内核数据结构实现了两
个目的。
ready list中的成员是interest list的子集。
对于由epoll检查的每一个文件描述符,我们可以指定一个位掩码来表示我们感兴趣的事
件。这些位掩码同poll()所使用的位掩码有着紧密的关联。
. . .
. . .
随着互联网的不断发展,各种类型的应用层出不穷,所以导致在这个云计算的时代,
对技术提出了更多的需求,主要体现在下面这四个方面:
庞大运营成本的考量:IT经理们希望在硬件成本、软件成本和人力成本能够有大幅度地降低;
目前世界上主流的存储系统大部分还是采用了关系型数据库,其主要有一下优点:
虽然关系型数据库已经在业界的数据存储方面占据不可动摇的地位,但是由于其天生的几个限制,
使其很难满足上面这几个需求:
业界为了解决上面提到的几个需求,推出了多款新类型的数据库,并且由于它们在设计上和传统的NoSQL数据库相比有很大的不同,
所以被统称为“NoSQL”系列数据库。
总的来说,在设计上,它们非常关注对数据高并发地读写和对海量数据的存储等,与关系型数据库相比,它们在架构和数据模型方量面做了“减法”,
而在扩展和并发等方面做了“加法”。
现在主流的NoSQL数据库有MongoDB和Redis以及BigTable、Hbase、Cassandra、SimpleDB、CouchDB、等。
接下来,将关注NoSQL数据库到底存在哪些优缺点。
在优势方面,主要体现在下面这三点:
但瑕不掩瑜,NoSQL数据库还存在着很多的不足,常见主要有下面这几个:
上面NoSQL产品的优缺点都是些比较共通的,在实际情况下,每个产品都会根据自己所遵从的数据模型和CAP理念而有所不同.
通常我们使用gcc来生成可执行程序,命令为:gcc hello.c,默认生成可执行文件a.out
其实编译(包括链接)的命令:gcc hello.c 可分解为如下4个大的步骤:
1. 预处理(Preproceessing)
预处理的过程主要处理包括以下过程:
通常使用以下命令来进行预处理:
gcc -E hello.c -o hello.i
参数-E表示只进行预处理 或者也可以使用以下指令完成预处理过程
cpp hello.c > hello.i / cpp – The C Preprocessor /
直接cat hello.i 你就可以看到预处理后的代码
2. 编译(Compilation)
编译过程就是把预处理完的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码。
$gcc –S hello.i –o hello.s
或者
$ /usr/lib/gcc/i486-linux-gnu/4.4/cc1 hello.c
注:现在版本的GCC把预处理和编译两个步骤合成一个步骤,用cc1工具来完成。gcc其实是后台程序的一些包装,根据不同参数去调用其他的实际处理程序,比如:预编译编译程序cc1、汇编器as、连接器ld
可以看到编译后的汇编代码(hello.s)如下:
.file "hello.c" |
3. 汇编(Assembly)
汇编器是将汇编代码转变成机器可以执行的命令,每一个汇编语句几乎都对应一条机器指令。汇编相对于编译过程比较简单,根据汇编指令和机器指令的对照表一一翻译即可。
$ gcc –c hello.c –o hello.o
或者
$ as hello.s –o hello.co
由于hello.o的内容为机器码,不能以普通文本形式的查看(vi 打开看到的是乱码)。
4. 链接(Linking)
通过调用链接器ld来链接程序运行需要的一大堆目标文件,以及所依赖的其它库文件,最后生成可执行文件。
ld -static crt1.o crti.o crtbeginT.o hello.o -start-group -lgcc -lgcc_eh -lc-end-group crtend.o crtn.o (省略了文件的路径名)。
helloworld的大体编译和链接过程就是这样了,那么编译器和链接器到底做了什么呢?
编译过程可分为6步:
链接的主要内容是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确地衔接。
链接的主要过程包括:地址和空间分配(Address and Storage Allocation),符号决议(Symbol Resolution),重定位(Relocation)等。
静态链接是指在编译阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。
动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。
静态链接的大致过程如下图所示:
摘自http://valgrind.org/docs/manual/faq.html#faq.deflost
5.2.With Memcheck’s memory leak detector, what’s the difference between “definitely lost”, “indirectly lost”, “possibly lost”, “still reachable”, and “suppressed”?
The details are in the Memcheck section of the user manual.
In short:
“definitely lost” means your program is leaking memory – fix those leaks!
“indirectly lost” means your program is leaking memory in a pointer-based structure. (E.g. if the root node of a binary tree is “definitely lost”, all the children will be “indirectly lost”.) If you fix the “definitely lost” leaks, the “indirectly lost” leaks should go away.
“possibly lost” means your program is leaking memory, unless you’re doing unusual things with pointers that could cause them to point into the middle of an allocated block; see the user manual for some possible causes. Use –show-possibly-lost=no if you don’t want to see these reports.
“still reachable” means your program is probably ok – it didn’t free some memory it could have. This is quite common and often reasonable. Don’t use –show-reachable=yes if you don’t want to see these reports.
“suppressed” means that a leak error has been suppressed. There are some suppressions in the default suppression files. You can ignore suppressed errors.
“definitely lost”:确认丢失。程序中存在内存泄露,应尽快修复。当程序结束时如果一块动态分配的内存没有被释放且通过程序内的指针变量均无法访问这块内存则会报这个错误。
“indirectly lost”:间接丢失。当使用了含有指针成员的类或结构时可能会报这个错误。这类错误无需直接修复,他们总是与”definitely lost”一起出现,只要修复”definitely lost”即可。例子可参考我的例程。
“possibly lost”:可能丢失。大多数情况下应视为与”definitely lost”一样需要尽快修复,除非你的程序让一个指针指向一块动态分配的内存(但不是这块内存起始地址),然后通过运算得到这块内存起始地址,再释放它。例子可参考我的例程。当程序结束时如果一块动态分配的内存没有被释放且通过程序内的指针变量均无法访问这块内存的起始地址,但可以访问其中的某一部分数据,则会报这个错误。
“still reachable”:可以访问,未丢失但也未释放。如果程序是正常结束的,那么它可能不会造成程序崩溃,但长时间运行有可能耗尽系统资源,因此笔者建议修复它。如果程序是崩溃(如访问非法的地址而崩溃)而非正常结束的,则应当暂时忽略它,先修复导致程序崩溃的错误,然后重新检测。
“suppressed”:已被解决。出现了内存泄露但系统自动处理了。可以无视这类错误。这类错误我没能用例程触发,看官方的解释也不太清楚是操作系统处理的还是valgrind,也没有遇到过。所以无视他吧~
#include <stdio.h> |
执行编译命令g++ val_test.cpp -o v
, 然后
当执行valgrind ./v
命令之后的简易内存错误报告 :
==4765== Memcheck, a memory error detector
==4765== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4765== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==4765== Command: ./v
==4765==
==4765==
==4765== HEAP SUMMARY:
==4765== in use at exit: 106 bytes in 4 blocks
==4765== total heap usage: 4 allocs, 0 frees, 106 bytes allocated
==4765==
==4765== LEAK SUMMARY:
==4765== definitely lost: 16 bytes in 1 blocks
==4765== indirectly lost: 40 bytes in 1 blocks
==4765== possibly lost: 30 bytes in 1 blocks
==4765== still reachable: 20 bytes in 1 blocks
==4765== suppressed: 0 bytes in 0 blocks
==4765== Rerun with --leak-check=full to see details of leaked memory
==4765==
==4765== For counts of detected and suppressed errors, rerun with: -v
==4765== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
b@b-VirtualBox:~/tc/valgrind_test$ valgrind --leak-check=full
valgrind: no program specified
valgrind: Use --help for more information.
当执行valgrind --leak-check=full ./v
命令之后的详细内存错误报告 :
==4767== Memcheck, a memory error detector
==4767== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4767== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==4767== Command: ./v
==4767==
==4767==
==4767== HEAP SUMMARY:
==4767== in use at exit: 106 bytes in 4 blocks
==4767== total heap usage: 4 allocs, 0 frees, 106 bytes allocated
==4767==
==4767== 30 bytes in 1 blocks are possibly lost in loss record 2 of 4
==4767== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4767== by 0x40055E: fun1() (val_test.cpp:12)
==4767== by 0x4005AB: main (val_test.cpp:20)
==4767==
==4767== 56 (16 direct, 40 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4
==4767== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4767== by 0x40053F: fun1() (val_test.cpp:10)
==4767== by 0x4005AB: main (val_test.cpp:20)
==4767==
==4767== LEAK SUMMARY:
==4767== definitely lost: 16 bytes in 1 blocks
==4767== indirectly lost: 40 bytes in 1 blocks
==4767== possibly lost: 30 bytes in 1 blocks
==4767== still reachable: 20 bytes in 1 blocks
==4767== suppressed: 0 bytes in 0 blocks
==4767== Reachable blocks (those to which a pointer was found) are not shown.
==4767== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==4767==
==4767== For counts of detected and suppressed errors, rerun with: -v
==4767== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
是啊,局部变量是栈变量,如果你不能把这个栈变量处理好,出了这个函数,指针地址就丢失了,这时那是肯定丢失了.
如果你付给的地址是全局变量,倒是可以访问,叫still reachable
但是如果你这个全局变量的值改动过, 那只有你知道怎样正确访问这块内存,别人可能就访问不到了,这叫可能丢失.
由肯定丢失而引起的进一步的内存丢失为间接丢失.
所以碰到问题你首先要解决什么问题?
肯定丢失,
然后是可能丢失,
然后间接丢失,
然后still reachable!!!