基础知识之Memcache
2016-09-21 11:56
253 查看
1、memcache的概念?
Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。在动态系统中减少数据库负载,提升性能。
memcache模块是一个高效的守护进程,提供用于内存缓存的过程式程序和面向对象的方便的接口,特别是对于设计动态web程序时减少对数据库的访问
2:作用:它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable。
3:Memcache官方网站:http://www.danga.com/memcached,更多详细的信息可以来这里了解 :)
为什么会有Memcache和memcached两种名称?
其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名。一个是项目名称,一个是主程序文件名,在网上看到了很多人不明白,于是混用了。
4:适用场合
1)分布式应用。由于memcached本身基于分布式的系统,所以尤其适合大型的分布式系统。
2)数据库前段缓存。数据库常常是网站系统的瓶颈。数据库的大并发量访问,常常造成网站内存溢出。当然我们也可以使用Hibernate的缓存机制。但memcached是基于分布式的,并可独立于网站应用本身,所以更适合大型网站进行应用的拆分。
3)服务器间数据共享。举例来讲,我们将网站的登录系统、查询系统拆分为两个应用,放在不同的服务器上,并进行集群,那这个时候用户登录后,登录信息如何从登录系统服务器同步到查询系统服务器呢?这时候,我们便可以使用memcached,登录系统将登录信息缓存起来,查询系统便可以获得登录信息,就像获取本地信息一样。
5:不适用场合
那些不需要“分布”的,不需要共享的,或者干脆规模小到只有一台服务器的应用,memcached不会带来任何好处,相反还会拖慢系统效率,因为网络连接同样需要资源.
【Memcache在中型网站的使用】
使用Memcache的网站一般流量都是比较大的,为了缓解数据库的压力,让Memcache作为一个缓存区域,把部分信息保存在内存中,在前端能够迅速的进行存取。那么一般的焦点就是集中在如何分担数据库压力和进行分布式,毕竟单台Memcache的内存容量的有限的。我这里简单提出我的个人看法,未经实践,权当参考。
[ 分布式应用]
Memcache本来支持分布式,我们客户端稍加改造,更好的支持。我们的key可以适当进行有规律的封装,比如以user为主的网站来说,每个用户都有UserID,那么可以按照固定的ID来进行提取和存取,比如1开头的用户保存在第一台Memcache服务器上,以2开头的用户的数据保存在第二胎Mecache服务器上,存取数据都先按照User ID来进行相应的转换和存取。
但是这个有缺点,就是需要对User ID进行判断,如果业务不一致,或者其他类型的应用,可能不是那么合适,那么可以根据自己的实际业务来进行考虑,或者去想更合适的方法。
[ 减少数据库压力]
这个算是比较重要的,所有的数据基本上都是保存在数据库当中的,每次频繁的存取数据库,导致数据库性能极具下降,无法同时服务更多的用户,比如MySQL,特别频繁的锁表,那么让Memcache来分担数据库的压力吧。我们需要一种改动比较小,并且能够不会大规模改变前端的方式来进行改变目前的架构。
我考虑的一种简单方法:
后端的数据库操作模块,把所有的Select操作提取出来(update/delete/insert不管),然后把对应的SQL进行相应的hash算法计算得出一个hash数据key(比如MD5或者SHA),然后把这个key去Memcache中查找数据,如果这个数据不存在,说明还没写入到缓存中,那么从数据库把数据提取出来,一个是数组类格式,然后把数据在set到Memcache中,key就是这个SQL的hash值,然后相应的设置一个失效时间,比如一个小时,那么一个小时中的数据都是从缓存中提取的,有效减少数据库的压力。
缺点是数据不实时,当数据做了修改以后,无法实时到前端显示,并且还有可能对内存占用比较大,毕竟每次select出来的数据数量可能比较巨大,这个是需要考虑的因素。
上面只是我两点没有经过深思熟虑的简单想法,也许有用,那就最好了。
【Memcache的安全】
我们上面的Memcache服务器端都是直接通过客户端连接后直接操作,没有任何的验证过程,这样如果服务器是直接暴露在互联网上的话是比较危险,轻则数据泄露被其他无关人员查看,重则服务器被入侵,因为Mecache是以root权限运行的,况且里面可能存在一些我们未知的bug或者是缓冲区溢出的情况,这些都是我们未知的,所以危险性是可以预见的。
为了安全起见,我做两点建议,能够稍微的防止黑客的入侵或者数据的泄露。
[ 内网访问]
最好把两台服务器之间的访问是内网形态的,一般是Web服务器跟Memcache服务器之间。普遍的服务器都是有两块网卡,一块指向互联网,一块指向内网,那么就让Web服务器通过内网的网卡来访问Memcache服务器,我们Memcache的服务器上启动的时候就监听内网的IP地址和端口,内网间的访问能够有效阻止其他非法的访问。
# memcached -d -m 1024?? -u root -l 192.168.0.200 -p 11211 -c 1024 -P /tmp/memcached.pid
Memcache服务器端设置监听通过内网的192.168.0.200的ip的11211端口,占用1024MB内存,并且允许最大1024个并发连接
[ 设置防火墙]
防火墙是简单有效的方式,如果却是两台服务器都是挂在网的,并且需要通过外网IP来访问Memcache的话,那么可以考虑使用防火墙或者代理程序来过滤非法访问。
一般我们在Linux下可以使用iptables或者FreeBSD下的ipfw来指定一些规则防止一些非法的访问,比如我们可以设置只允许我们的Web服务器来访问我们Memcache服务器,同时阻止其他的访问。
# iptables -F
# iptables -P INPUT DROP
# iptables -A INPUT -p tcp -s 192.168.0.2 --dport 11211 -j ACCEPT
# iptables -A INPUT -p udp -s 192.168.0.2 --dport 11211 -j ACCEPT
上面的iptables规则就是只允许192.168.0.2这台Web服务器对Memcache服务器的访问,能够有效的阻止一些非法访问,相应的也可以增加一些其他的规则来加强安全性,这个可以根据自己的需要来做。
【Memcache的扩展性】
Memcache算是比较简洁高效的程序,Memcache 1.2.0 的源代码大小才139K,在Windows平台上是不可想象的,但是在开源世界来说,这是比较正常合理的。
Memcache目前都只是比较简单的功能,简单的数据存取功能,我个人希望如果有识之士,能够在下面两方面进行扩展。
1. 日志功能
目前Memcache没有日志功能,只有一些命令在服务器端进行回显,这样是很不利于对一个服务器的稳定性和负载等等进行监控的,最好能够相应的加上日志的等功能,便于监控。
2. 存储结构
目前的数据形式就是: key => data 的形式,特别单一,只能够存储单一的一维数据,如果能够扩展的话,变成类似数据库的格式,能够存储二维数据,那样会让可以用性更强,使用面更广,当然相应的可能代码效率和存取效率更差一些。
3. 同步功能
数据同步是个比较重要的技术,因为谁都不能保证一台服务器是持久正常的运行的,如果能够具有类似MySQL的 Master/Slave的功能,那么将使得Memcache的数据更加稳定,那么相应的就可以考虑存储持久一点的数据,并且不用害怕Memcache的down掉,因为有同步的备份服务器,这个问题就不是问题了。
以上三点只是个人拙见,有识之士和技术高手可以考虑。
【memcache的细节讨论】
① 生命周期
从数据放入mem开始计时,直到时间到了,就销毁, 如果时间为0, 则表示不过期.
memcache的数据被销毁的情况如下:
1. 时间到
2. 重启memcached服务
3. 重启memcached服务所在的机器
4. delete / flush 销毁数据
② 如何把session数据放入到memcached服务中.
步骤:
1. 修改php.ini的配置文件
如下:
;[sesson.save_handler有user|files|memcache]
session.save_handler= memcache
session.save_path= "tcp://127.0.0.1:11211"
③ 测试一把,重启apache
测试ok
<?php
//传统的代码
session_start();
$_SESSION['name']='天龙八部300';
$_SESSION['city']='beijing';
class Dog{
public $name;
}
$dog1=new Dog;
$dog1->name='abcde';
$_SESSION['dog']=$dog1;
//如果session数据入mem,那他一定是以session_id为
//key值进行添加
//取出
$name=$_SESSION['name'];
echo "name=$name";
echo "sessionid=".session_id();
思考,如果管理员,不让我们修改php.ini 文件,我们如何处理session入memcached这个功能, 我们通过一个函数可以去修改 php.ini 的配置.
代码:
<?php
ini_set("session.save_handler","memcache");
ini_set("session.save_path","tcp://127.0.0.1:9999");
同时你也可以通过 ini_set 去动态的修改对php.ini 的其它设置 。但是他不影响其它php页面,也不会去修改php.ini 文件本身, 只对本页面生效.
memcached vs session比较
memcached 主要的目的是提速 ,因此它是一种无状态的数据.即,数据不和用户绑定.
session数据是和用户绑定的,因此是一种有状态数据.
Memcached一些特性和限制
? 在 Memcached 中可以保存的item数据量是没有限制的,只有内存足够
? Memcached单进程最大使用内存为2G,要使用更多内存,可以分多个端口开启多个Memcached进程
? 最大30天的数据过期时间, 设置为永久的也会在这个时间过期,常量REALTIME_MAXDELTA
60*60*24*30 控制
? 最大键长为250字节,大于该长度无法存储,常量KEY_MAX_LENGTH 250 控制
? 单个item最大数据是1MB,超过1MB数据不予存储,常量POWER_BLOCK 1048576 进行控制,
它是默认的slab大小
? 最大同时连接数是200,通过 conn_init()中的freetotal 进行控制,最大软连接数是1024,通过
settings.maxconns=1024 进行控制
? 跟空间占用相关的参数:settings.factor=1.25, settings.chunk_size=48, 影响slab的数据占用和步进方式
什么样的数据适合放入memcached中?
1)变化频繁,具有不稳定性的数据,不需要实时入库,如在线用户,session信息
2)和memcached技术类似是redis (key/value数据库),也是把数据放在内存中,并定时向磁盘同步
memcached的基本命令(安装、卸载、启动、配置相关):
-p 监听的端口
-l 连接的IP地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间,key+value+flags默认是48
-h 显示帮助
memcached的基本命令(当memcached 启动后 用于对memcached管理的数据和本身运行状态相关的命令):
对查看的信息的关键字中英文对照表
Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。在动态系统中减少数据库负载,提升性能。
memcache模块是一个高效的守护进程,提供用于内存缓存的过程式程序和面向对象的方便的接口,特别是对于设计动态web程序时减少对数据库的访问
2:作用:它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这些HashTable。
3:Memcache官方网站:http://www.danga.com/memcached,更多详细的信息可以来这里了解 :)
为什么会有Memcache和memcached两种名称?
其实Memcache是这个项目的名称,而memcached是它服务器端的主程序文件名。一个是项目名称,一个是主程序文件名,在网上看到了很多人不明白,于是混用了。
4:适用场合
1)分布式应用。由于memcached本身基于分布式的系统,所以尤其适合大型的分布式系统。
2)数据库前段缓存。数据库常常是网站系统的瓶颈。数据库的大并发量访问,常常造成网站内存溢出。当然我们也可以使用Hibernate的缓存机制。但memcached是基于分布式的,并可独立于网站应用本身,所以更适合大型网站进行应用的拆分。
3)服务器间数据共享。举例来讲,我们将网站的登录系统、查询系统拆分为两个应用,放在不同的服务器上,并进行集群,那这个时候用户登录后,登录信息如何从登录系统服务器同步到查询系统服务器呢?这时候,我们便可以使用memcached,登录系统将登录信息缓存起来,查询系统便可以获得登录信息,就像获取本地信息一样。
5:不适用场合
那些不需要“分布”的,不需要共享的,或者干脆规模小到只有一台服务器的应用,memcached不会带来任何好处,相反还会拖慢系统效率,因为网络连接同样需要资源.
【Memcache在中型网站的使用】
使用Memcache的网站一般流量都是比较大的,为了缓解数据库的压力,让Memcache作为一个缓存区域,把部分信息保存在内存中,在前端能够迅速的进行存取。那么一般的焦点就是集中在如何分担数据库压力和进行分布式,毕竟单台Memcache的内存容量的有限的。我这里简单提出我的个人看法,未经实践,权当参考。
[ 分布式应用]
Memcache本来支持分布式,我们客户端稍加改造,更好的支持。我们的key可以适当进行有规律的封装,比如以user为主的网站来说,每个用户都有UserID,那么可以按照固定的ID来进行提取和存取,比如1开头的用户保存在第一台Memcache服务器上,以2开头的用户的数据保存在第二胎Mecache服务器上,存取数据都先按照User ID来进行相应的转换和存取。
但是这个有缺点,就是需要对User ID进行判断,如果业务不一致,或者其他类型的应用,可能不是那么合适,那么可以根据自己的实际业务来进行考虑,或者去想更合适的方法。
[ 减少数据库压力]
这个算是比较重要的,所有的数据基本上都是保存在数据库当中的,每次频繁的存取数据库,导致数据库性能极具下降,无法同时服务更多的用户,比如MySQL,特别频繁的锁表,那么让Memcache来分担数据库的压力吧。我们需要一种改动比较小,并且能够不会大规模改变前端的方式来进行改变目前的架构。
我考虑的一种简单方法:
后端的数据库操作模块,把所有的Select操作提取出来(update/delete/insert不管),然后把对应的SQL进行相应的hash算法计算得出一个hash数据key(比如MD5或者SHA),然后把这个key去Memcache中查找数据,如果这个数据不存在,说明还没写入到缓存中,那么从数据库把数据提取出来,一个是数组类格式,然后把数据在set到Memcache中,key就是这个SQL的hash值,然后相应的设置一个失效时间,比如一个小时,那么一个小时中的数据都是从缓存中提取的,有效减少数据库的压力。
缺点是数据不实时,当数据做了修改以后,无法实时到前端显示,并且还有可能对内存占用比较大,毕竟每次select出来的数据数量可能比较巨大,这个是需要考虑的因素。
上面只是我两点没有经过深思熟虑的简单想法,也许有用,那就最好了。
【Memcache的安全】
我们上面的Memcache服务器端都是直接通过客户端连接后直接操作,没有任何的验证过程,这样如果服务器是直接暴露在互联网上的话是比较危险,轻则数据泄露被其他无关人员查看,重则服务器被入侵,因为Mecache是以root权限运行的,况且里面可能存在一些我们未知的bug或者是缓冲区溢出的情况,这些都是我们未知的,所以危险性是可以预见的。
为了安全起见,我做两点建议,能够稍微的防止黑客的入侵或者数据的泄露。
[ 内网访问]
最好把两台服务器之间的访问是内网形态的,一般是Web服务器跟Memcache服务器之间。普遍的服务器都是有两块网卡,一块指向互联网,一块指向内网,那么就让Web服务器通过内网的网卡来访问Memcache服务器,我们Memcache的服务器上启动的时候就监听内网的IP地址和端口,内网间的访问能够有效阻止其他非法的访问。
# memcached -d -m 1024?? -u root -l 192.168.0.200 -p 11211 -c 1024 -P /tmp/memcached.pid
Memcache服务器端设置监听通过内网的192.168.0.200的ip的11211端口,占用1024MB内存,并且允许最大1024个并发连接
[ 设置防火墙]
防火墙是简单有效的方式,如果却是两台服务器都是挂在网的,并且需要通过外网IP来访问Memcache的话,那么可以考虑使用防火墙或者代理程序来过滤非法访问。
一般我们在Linux下可以使用iptables或者FreeBSD下的ipfw来指定一些规则防止一些非法的访问,比如我们可以设置只允许我们的Web服务器来访问我们Memcache服务器,同时阻止其他的访问。
# iptables -F
# iptables -P INPUT DROP
# iptables -A INPUT -p tcp -s 192.168.0.2 --dport 11211 -j ACCEPT
# iptables -A INPUT -p udp -s 192.168.0.2 --dport 11211 -j ACCEPT
上面的iptables规则就是只允许192.168.0.2这台Web服务器对Memcache服务器的访问,能够有效的阻止一些非法访问,相应的也可以增加一些其他的规则来加强安全性,这个可以根据自己的需要来做。
【Memcache的扩展性】
Memcache算是比较简洁高效的程序,Memcache 1.2.0 的源代码大小才139K,在Windows平台上是不可想象的,但是在开源世界来说,这是比较正常合理的。
Memcache目前都只是比较简单的功能,简单的数据存取功能,我个人希望如果有识之士,能够在下面两方面进行扩展。
1. 日志功能
目前Memcache没有日志功能,只有一些命令在服务器端进行回显,这样是很不利于对一个服务器的稳定性和负载等等进行监控的,最好能够相应的加上日志的等功能,便于监控。
2. 存储结构
目前的数据形式就是: key => data 的形式,特别单一,只能够存储单一的一维数据,如果能够扩展的话,变成类似数据库的格式,能够存储二维数据,那样会让可以用性更强,使用面更广,当然相应的可能代码效率和存取效率更差一些。
3. 同步功能
数据同步是个比较重要的技术,因为谁都不能保证一台服务器是持久正常的运行的,如果能够具有类似MySQL的 Master/Slave的功能,那么将使得Memcache的数据更加稳定,那么相应的就可以考虑存储持久一点的数据,并且不用害怕Memcache的down掉,因为有同步的备份服务器,这个问题就不是问题了。
以上三点只是个人拙见,有识之士和技术高手可以考虑。
【memcache的细节讨论】
① 生命周期
从数据放入mem开始计时,直到时间到了,就销毁, 如果时间为0, 则表示不过期.
memcache的数据被销毁的情况如下:
1. 时间到
2. 重启memcached服务
3. 重启memcached服务所在的机器
4. delete / flush 销毁数据
② 如何把session数据放入到memcached服务中.
步骤:
1. 修改php.ini的配置文件
如下:
;[sesson.save_handler有user|files|memcache]
session.save_handler= memcache
session.save_path= "tcp://127.0.0.1:11211"
③ 测试一把,重启apache
测试ok
<?php
//传统的代码
session_start();
$_SESSION['name']='天龙八部300';
$_SESSION['city']='beijing';
class Dog{
public $name;
}
$dog1=new Dog;
$dog1->name='abcde';
$_SESSION['dog']=$dog1;
//如果session数据入mem,那他一定是以session_id为
//key值进行添加
//取出
$name=$_SESSION['name'];
echo "name=$name";
echo "sessionid=".session_id();
思考,如果管理员,不让我们修改php.ini 文件,我们如何处理session入memcached这个功能, 我们通过一个函数可以去修改 php.ini 的配置.
代码:
<?php
ini_set("session.save_handler","memcache");
ini_set("session.save_path","tcp://127.0.0.1:9999");
同时你也可以通过 ini_set 去动态的修改对php.ini 的其它设置 。但是他不影响其它php页面,也不会去修改php.ini 文件本身, 只对本页面生效.
memcached vs session比较
memcached 主要的目的是提速 ,因此它是一种无状态的数据.即,数据不和用户绑定.
session数据是和用户绑定的,因此是一种有状态数据.
Memcached一些特性和限制
? 在 Memcached 中可以保存的item数据量是没有限制的,只有内存足够
? Memcached单进程最大使用内存为2G,要使用更多内存,可以分多个端口开启多个Memcached进程
? 最大30天的数据过期时间, 设置为永久的也会在这个时间过期,常量REALTIME_MAXDELTA
60*60*24*30 控制
? 最大键长为250字节,大于该长度无法存储,常量KEY_MAX_LENGTH 250 控制
? 单个item最大数据是1MB,超过1MB数据不予存储,常量POWER_BLOCK 1048576 进行控制,
它是默认的slab大小
? 最大同时连接数是200,通过 conn_init()中的freetotal 进行控制,最大软连接数是1024,通过
settings.maxconns=1024 进行控制
? 跟空间占用相关的参数:settings.factor=1.25, settings.chunk_size=48, 影响slab的数据占用和步进方式
什么样的数据适合放入memcached中?
1)变化频繁,具有不稳定性的数据,不需要实时入库,如在线用户,session信息
2)和memcached技术类似是redis (key/value数据库),也是把数据放在内存中,并定时向磁盘同步
memcached的基本命令(安装、卸载、启动、配置相关):
-p 监听的端口
-l 连接的IP地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间,key+value+flags默认是48
-h 显示帮助
memcached的基本命令(当memcached 启动后 用于对memcached管理的数据和本身运行状态相关的命令):
Command | Description | Example |
get | Reads a value | get mykey |
set | Set a key unconditionally | set mykey 0 60 5 |
add | Add a new key | add newkey 0 60 5 |
replace | Overwrite existing key | replace key 0 60 5 |
append | Append data to existing key | append key 0 60 15 |
prepend | Prepend data to existing key | prepend key 0 60 15 |
incr | Increments numerical key value by given number | incr mykey 2 |
decr | Decrements numerical key value by given number | decr mykey 5 |
delete | Deletes an existing key | delete mykey |
flush_all | Invalidate specific items immediately | flush_all |
Invalidate all items in n seconds | flush_all 900 | |
stats | Prints general statistics | stats |
Prints memory statistics | stats slabs | |
Prints memory statistics | stats malloc | |
Print higher level allocation statistics | stats items | |
| stats detail | |
| stats sizes | |
Resets statistics | stats reset | |
version | Prints server version. | version |
verbosity | Increases log level | verbosity |
quit | Terminate telnet session | quit |
对查看的信息的关键字中英文对照表
pid | memcache服务器的进程ID |
uptime | 服务器已经运行的秒数 |
time | 服务器当前的unix时间戳 |
version | memcache版本 |
pointer_size | 当前操作系统的指针大小(32位系统一般是32bit) |
rusage_user | 进程的累计用户时间 |
rusage_system | 进程的累计系统时间 |
curr_items | 服务器当前存储的items数量 |
total_items | 从服务器启动以后存储的items总数量 |
bytes | 当前服务器存储items占用的字节数 |
curr_connections | 当前打开着的连接数 |
total_connections | 从服务器启动以后曾经打开过的连接数 |
connection_structures | 服务器分配的连接构造数 |
cmd_get | get命令(获取)总请求次数 |
cmd_set | set命令(保存)总请求次数 |
get_hits | 总命中次数 |
get_misses | 总未命中次数 |
evictions | 为获取空闲内存而删除的items数(分配给memcache的空间用满后需要删除旧的items来得到空间分配给新的items) |
bytes_read | 总读取字节数(请求字节数) |
bytes_written | 总发送字节数(结果字节数) |
limit_maxbytes | 分配给memcache的内存大小(字节) |
threads | 当前线程数 |
相关文章推荐
- Memcache---基础知识篇
- 基础知识之Memcache的安装和测试
- memcache基础知识-stats参数
- MemCache基础知识介绍
- memcache基础知识大全
- memcache基础知识
- Memcache基础知识
- 第二讲 Java语言基础知识
- 色彩系列教程(1):基础知识
- 摄影基础知识汇总
- 建立个人网站的基础知识三:软件方面
- 加密和 PKI 基础知识
- OLAP与OLTP的一些基础知识
- 标准化基础知识
- 00014.网络基础知识
- Linux下C语言编程--基础知识
- 基础知识-如何查看MAC地址
- 复习一下 .Net: delegate(委托)、event(事件) 的基础知识,从头到尾实现事件!
- 刻录基础知识之刻录方式
- ASP.NET中Cookie编程的基础知识