1.memcached简介
Memcached 是一个自由开源的,高性能,分布式内存对象缓存系统。
Memcached 是以 LiveJournal 旗下 Danga Interactive 公司的 Brad
Fitzpatric 为首开发的一款软件。现在已成为 mixi、hatena、Facebook、Vox、LiveJournal 等众多服务中
提高 Web 应用扩展性的重要因素。
Memcached 是一种基于内存的 key-value 存储,用来存储小块的任意数据(字符串、对象)。这
些数据可以是数据库调用、API 调用或者是页面渲染的结果。
Memcached 简洁而强大。它的简洁设计便于快速开发,减轻开发难度,解决了大数据量缓存的
很多问题。它的 API 兼容大部分流行的开发语言。
本质上,它是一个简洁的 key-value 存储系统。
一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态 Web 应用的
速度、提高可扩展性。

2. Memcached 工作原理
Memcached 使用了 BSD 许可的服务端缓存实现。与其它服务端缓存实现不同的是,其主要由两
部分组成:独立运行的 Memcached 服务实例,以及用于访问这些服务实例的客户端。因此相较于普通服务端缓存实现中各个缓存都运行在服务实例之上的情况,Memcached 服务实例则是在服务实例之外独立运行的:

从上图中可以看出,由于 Memcached 缓存实例是独立于各个应用服务器实例运行的,因此应用服务实例可以访问任意的缓存实例。而传统的缓存则与特定的应用实例绑定,因此每个应用实例将只能访问特定的缓存。这种绑定一方面会导致整个应用所能够访问的缓存容量变得很小,另一方面也可能导致不同的缓存实例中存在着冗余的数据,从而降低了缓存系统的整体效率。
在运行时,Memcached 服务实例只需要消耗非常少的 CPU 资源,却需要使用大量的内存。因此在决定如何组织您的服务端缓存结构之前,您首先需要搞清当前服务中各个服务实例的负载情况。如果一个服务器的 CPU 使用率非常高,却存在着非常多的空余内存,那么我们就完全可以在其上运行一个 Memcached 实例。而如果当前服务中的所有服务实例都没有过多的空余内存,那么我们就需要使用一系列独立的服务实例来搭建服务端缓存。一个大型服务常常拥有上百个 Memcached 实例。而在这上百个 Memcached 实例中所存储的数据则不尽相同。由于这种数据的异构性,我们需要在访问由Memcached所记录的信息之前决定在该服务端缓存系统中到底由哪个Memcached实例记录了我们所想要访问的数据:

如上图所示,用户需要通过一个 Memcached 客户端来完成对缓存服务所记录信息的访问。该客
户端知道服务端缓存系统中所包含的所有 Memcached 服务实例。在需要访问具有特定键值的数据时,该客户端内部会根据所需要读取的数据的键值,如“foo”,以及当前 Memcached 缓存服务的配置来计算相应的哈希值,以决定到底是哪个 Memcached 实例记录了用户所需要访问的信息。在决定记录了所需要信息的 Memcached 实例之后,Memcached 客户端将从配置中读取该 Memcached 服务实例所在地址,并向该 Memcached 实例发送数据访问请求,以从该 Memcached 实例中读取具有键值“foo”的信息。而对数据的记录也使用了类似的流程:假设用户希望通过服务端缓存记录数据“bar”,并为其指定键值“foo”。那么 Memcached 客户端将首先对用户所赋予的键值“foo”及当前服务端缓存所记录的可用服务实例个数执行哈希计算,并根据哈希计算结果来决定存储该数据的 Memcached 服务实例。接下来,客户端就会向该实例发送请求,以在其中记录具有键值“foo”的数据“bar”。
这样做的好处则在于,每个 Memcached 服务实例都是独立的,而彼此之间并没有任何交互。在
这种情况下,我们可以省略很多复杂的功能逻辑,如各个节点之间的数据同步以及结点之间消息的广播等等。这种轻量级的架构可以简化很多操作。如在一个节点失效的时候,我们仅仅需要使用一个新的 Memcached 节点替代老节点即可。而在对缓存进行扩容的时候,我们也只需要添加额外的服务并修改客户端配置。
这些记录在服务端缓存中的数据是全局可见的。也就是说,一旦在 Memcached 服务端缓存中成
功添加了一条新的记录,那么其它使用该缓存服务的应用实例将同样可以访问该记录:

在 Memcached 中,每条记录都由四部分组成:记录的键,有效期,一系列可选的标记以及表示记录内容的数据。由于记录内容的数据中并不包含任何数据结构,因此我们在 Memcached 中所记录的数据需要是经过序列化之后的表示。

3.内存管理
通常情况下,一个内存管理算法所最需要考虑
的问题就是内存的碎片化(Fragmentation):在长时间地分配及回收之后,被系统所使用的内存将趋向于散落在不连续的空间中。这使得系统很难找到连续内存空间,一方面增大了内存分配失败的概率,另一方面也使得内存分配工作变得更为复杂,降低了运行效率。
为了解决这个问题,Memcached 使用了一种叫 Slab 的结构。在该分配算法中,内存将按照 1MB的大小划分为页,而该页内存则会继续被分割为一系列具有相同大小的内存块。

因此 Memcached 并不是直接根据需要记录的数据的大小来直接分配相应大小的内存。在一条新的记录到来时,Memcached 会首先检查该记录的大小,并根据记录的大小选择记录所需要存储到的Slab 类型。接下来,Memcached 就会检查其内部所包含的该类型 Slab。如果这些 Slab 中有空余的块,那么 Memcached 就会使用该块记录该条信息。如果已经没有 Slab 拥有空闲的具有合适大小的块,那么 Memcached 就会创建一个新的页,并将该页按照目标 Slab 的类型进行划分。
Memcached 使用这种方式来分配内存的好处则在于,其可以降低由于记录的多次读写而导致的碎片化。反过来,由于 Memcached 是根据记录的大小选择需要插入到的块类型,因此为每个记录所分配的块的大小常常大于该记录所实际需要的内存大小,进而造成了内存的浪费。当然,您可以通过Memcached 的配置文件来指定各个块的大小,从而尽可能地减少内存的浪费。
但是需要注意的是,由于默认情况下 Memcached 中每页的大小为 1MB,因此其单个块最大为1MB。除此之外,Memcached 还限制每个数据所对应的键的长度不能超过 250个字节。
一般来说,Slab 中各个块的大小以及块大小的递增倍数可能会对记录所载位置的选择及内存利用率有很大的影响。例如在当前的实现下,各个 Slab 中块的大小默认情况下是按照 1.25 倍的方式来递增的。也就是说,在一个 Memcached 实例中,某种类型 Slab 所提供的块的大小是 80K,而提供稍大一点空间的 Slab 类型所提供的块的大小就将是 100K。如果现在我们需要插入一条 81K 的记录,那么Memcached 就会选择具有 100K 块大小的 Slab,并尝试找到一个具有空闲块的 Slab 以存入该记录。
同时您也需要注意到,我们使用的是 100K 块大小的 Slab 来记录具有 81K 大小的数据,因此记录该数据所导致的内存浪费是 19K,即 19%的浪费。而在需要存储的各条记录的大小平均分布的情况下,这种内存浪费的幅度也在 9%左右。该幅度实际上取决于我们刚刚提到的各个 Slab 中块大小的递增倍数。在 Memcached 的初始实现中,各个 Slab 块的递增倍数在默认情况下是 2,而不是现在的 1.25,从而导致了平均 25%左右的内存浪费。而在今后的各个版本中,该递增倍数可能还会发生变化,以优化 Memcached 的实际性能。
如果您一旦知道了您所需要缓存的数据的特征,如通常情况下数据的大小以及各个数据的差异幅度,那么您就可以根据这些数据的特征来设置上面所提到的各个参数。如果数据在通常情况下都比较小,那么我们就需要将最小块的大小调整得小一些。如果数据的大小变动不是很大,那么我们可以将块大小的递增倍数设置得小一些,从而使得各个块的大小尽量地贴近需要存储的数据,以提高内存的利用率。
还有一个值得注意的事情就是,由于 Memcached 在计算到底哪个服务实例记录了具有特定键的数据时并不会考虑用来组成缓存系统中各个服务器的差异性。如果每个服务器上只安装了一个Memcached 实例,那么各个 Memcached 实例所拥有的可用内存将存在着数倍的差异。但是由于各个实例被选中的概率基本相同,因此具有较大内存的 Memcached 实例将无法被充分利用。我们可以通过在具有较大内存的服务器上部署多个 Memcached 实例来解决这个问题:

当然,由于缓存系统拥有有限的资源,因此其会在某一时刻被服务所产生的数据填满。如果此时缓存系统再次接收到一个缓存数据的请求,那么它就会根据 LRU(Least recently used)算法以及数据的过期时间来决定需要从缓存系统中移除的数据。而 Memcached 所使用的过期算法比较特殊,又被称为延迟过期(Lazy expiration):当用户从 Memcached 实例中读取数据的时候,其将首先通过配置中所设置的过期时间来决定该数据是否过期。如果是,那么在下一次写入数据却没有足够空间的时候,Memcached 会选择该过期数据所在的内存块作为新数据的目标地址。如果在写入时没有相应的记录被标记为过期,那么 LRU 算法才被执行,从而找到最久没有被使用的需要被替换的数据。
这里的 LRU 是在 Slab 范围内的,而不是全局的。假设 Memcached 缓存系统中的最常用的数据都存储在 100K 的块中,而该系统中还存在着另外一种类型的 Slab,其块大小是 300K,但是存在于其中的数据并不常用。当需要插入一条 99K 的数据而 Memcached 已经没有足够的内存再次分配一个 Slab实例的时候,其并不会释放具有 300K 块大小的 Slab,而是在 100K 块大小的各个 Slab 中找到需要释放的块,并将新数据添加到该块中。
**4.memcached特点**
内存存储速度快,对于内存的要求高,所缓存的内容非持久化。对于 CPU 要求很低,所以常常采用将 Memcached 服务端和一些 CPU 高消耗 Memory 低消耗应用部属在一起 。(否则会互相挤占资源)集中式 Cache避开了分布式 Cache 的传播问题,但是需要非单点保证其可靠性,这需要 cluster 的工作,可以将多个 Memcached 作为一个虚拟的 cluster ,同时对于 cluster 的读写和普通的 memcached 的读写性能没有差别。

分布式扩展
Memcached 很突出的一个优点,就是采用了可分布式扩展的模式。可以将部属在一台机器上的多个 Memcached 服务端或者部署在多个机器上的 Memcached 服务端组成一个虚拟的服务端,对于调用者来说完全屏蔽和透明。提高的单机器的内存利用率 。
Socket 通信
传输内容的大小以及序列化的问题需要注意,虽然 Memcached 通常会被放置到内网作为
Cache, Socket 传输速率应该比较高(当前支持 Tcp 和 udp 两种模式,同时根据客户端的不同可以选择使用 nio 的同步或者异步调用方式),但是序列化成本和带宽成本还是需要注意。这里也提一下序列化,对于对象序列化的性能往往让大家头痛,但是如果对于同一类的 Class 对象序列化传输,第一次序列化时间比较长,后续就会优化,其实也就是说序列化最大的消耗不是对象序列化,而是类的序列化。如果穿过去的只是字符串,那么是最好的,省去了序列化的操作,因此在 Memcached 中保存的往往是较小的内容 。
特殊的内存分配机制
首先要说明的是 Memcached 支持最大的存储对象为 1M (page)。它的内存分配比较特殊,但是这样的分配方式其实也是对于性能考虑的,简单的分配机制可以更容易回收再分配,节省对于 CPU 的使用(前面的文章中有描述) 。
Cache 机制简单
首先它没有什么同步,消息分发,两阶段提交等等,它就是一个很简单的 Cache ,把东西放进去,然后可以取出来,如果发现所提供的 Key 没有命中,那么就很直白的告诉你,你这个 key 没有任何对应的东西在缓存里,去数据库或者其他地方取,当你在外部数据源取到的时候,可以直接将内容置入到 Cache 中,这样下次就可以命中了 。这里会提到怎么去同步这些数据,两种方式,一种就是在你修改了以后立刻更新 Cache 内容,这样就会即时生效。另一种是说容许有失效时间,到了失效时间,自然就会将内容删除,此时再去去的时候就会命中不了,然后再次将内容置入 Cache ,用来更新内容。后者用在一些时时性要求不高,写入不频繁的情况。
4.memcached应用场景
(1).Web缓存
场景介绍
想象有这么一个场景,一个电子商务网站,在网站的左侧会是商品的分类,中间是商品搜索结果的列表,可以查看商品信息和商家的基本信息和相关商家的信誉度信息。
在这个场景下,因为一个商场的类别不会经常改变的。实时性不是很高,这样应该放到缓存中取的。
一般时候做法:
执行一次或者多次sql从数据库中查询全站的商品分类---->>递归形成你所需的分类tree------>>进入处理数据------->>显示到页面上。
在使用 memcached做法:
第一次显示的时候:判断memcached缓存中是否有该分类----没有----->执行一次或者多次sql从数据库中查询全站的商品分类----->放到memcached中------->>进入处理数据------->>显示到页面
第二次显示的判断memcached缓存中是否有该分类----有—>>-从memcached中取出数据-------->>进入处理数据------->>显示到页面
当这个过程首次发生时,数据将正常地从数据库或其他数据源加载,然后再存储到 memcached 内。当下一次访问此信息时,它就会从 memcached 中取出,而不是从数据库加载,节省了时间和 CPU 循环。
但是要是数据中的数据改变怎么来更新memcached中的数据呢
过程为:更新数据库中分类的信息------->找到memcached中key值,删除------>重新插入到你的memcached中就可以了
memcached 内的存储操作是原子的,所以信息的更新不会让客户机只获得部分数据;它们获得的或者是老版本,或者是新版本。
当这个过程首次发生时,数据将正常地从数据库或其他数据源加载,然后再存储到 memcached 内。当下一次访问此信息时,它就会从 memcached 中取出,而不是从数据库加载,节省了时间和 CPU 循环。
但是要是数据中的数据改变怎么来更新memcached中的数据呢
过程为:更新数据库中分类的信息------->找到memcached中key值,删除------>重新插入到你的memcached中就可以了
memcached 内的存储操作是原子的,所以信息的更新不会让客户机只获得部分数据;它们获得的或者是老版本,或者是新版本。
(2).数据库缓存
实际应用中,尤其是在大规模访问的Web项目中,Memcache作为一种优秀的缓存解决方案,被广泛使用。其灵活性和可扩展性受到了广大开发者的青睐。为了提高响应速度,使用Memcache来减少数据查询运算是一种不错的选择。
需求背景:网站有一个图片放映功能,页面加载时需从数据库中查询管理员所提交放映的图片信息,图片放映区共有9张图片,对应在数据库表中有9条记录。每次用户访问网站时,需查询数据库,并显示图片。当承受大规模用户同时访问时,数据库的压力可想而之。
为了降低数据库压力,提高查询速度,我采用了Memcache来将图片记录信息缓存到Memcache服务器上。这样就将数据库的查询压力分散到了各缓存服务器,提高了网站访问的整体效率。
(3)基础环境配置
环境规划
192.168.42.186 : memcache
192.168.42.187 : web
192.168.42.181 :mysql
同步时间:

yum -y install ntp
ntpdate ntpdate cn.pool.ntp.org
hwclock --systohc

关闭防火墙

systemctl stop firewalld
systemctl disable firewalld
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0
rpm -e mariadb-libs postfix

(4)web服务器配置
在192.168.42.145
安装软件,启动服务

wget https://downloads.mysql.com/archives/get/file/mysql-community-libs-compat-
8.0.16-2.el7.x86_64.rpm
yum localinstall mysql-community-client-8.0.16-2.el7.x86_64.rpm mysql-community-
server-8.0.16-2.el7.x86_64.rpm mysql-community-libs-8.0.16-2.el7.x86_64.rpm
mysql-community-common-8.0.16-2.el7.x86_64.rpm mysql-community-libs-compat-
8.0.16-2.el7.x86_64.rpm
yum install http php php-gb php-mysql php-memcache
systemctl restart httpd
systemctl enable httpd
systemctl restart mysql
systemctl enable mysql 

在服务端创建用户:

mysql> create user 'memcache'@'%' identified by 'Cloudbu@123';
mysql> ALTER USER 'memcache'@'%' IDENTIFIED WITH mysql_native_password BY 'Cloudbu@123';
mysql> flush privileges;

测试http功能。

[root@localhost ~]# vim /var/www/html/index.html
[root@localhost ~]# cat /var/www/html/index.html
this is a test form 187..

测试PHP链接功能

vim /var/www/html/index.php
cat /var/www/html/index.php<?phpphpinfo();?>

测试mysql

<?php
$link=mysql_connect('192.168.42.181','superadmin','Cloudbu@123');
if($link) echo "<h1>Success!!</h1>";
else echo "Fail!!";
mysql_close();
?>

(5)memcache 服务配置
参考memcache安装
功能测试
测试web和memcache的连通性;
修改客户端监听所有地址

[root@localhost ~]# /usr/local/memcached/bin/memcached -d -l 0.0.0.0 -p 11211 -u
root -m 64 -c 1024 -P /var/run/memcached.pid
[root@localhost ~]# ps -ef |grep memcached
root 16629 1 0 02:38 ? 00:00:00
/usr/local/memcached/bin/memcached -d -l 0.0.0.0 -p 11211 -u root -m 64 -c 1024
-P /var/run/memcached.pid
root 16640 16561 0 02:38 pts/1 00:00:00 grep --color=auto memcached

代码测试

<?php
$memcache = new Memcache;
$memcache->connect('192.168.42.186', 11211) or die ("Could not connect");
$version = $memcache->getVersion();
echo "Server's version: ".$version."<br/>";
$tmp_object = new stdClass;
$tmp_object->str_attr = 'test';
$tmp_object->int_attr = 123;
$memcache->set('key', $tmp_object, false, 10) or die ("Failed to save data at
the server");
echo "Store data in the cache (data will expire in 10 seconds)<br/>";
$get_result = $memcache->get('key');
echo "Data from the cache:<br/>";
var_dump($get_result);
?>

配置session:
vim /etc/php.ini
session.save_handler = memcache
session.save_path = “tcp://192.168.42.145:11211?
persistent=1&weight=1&timeout=1&retry_interval=15”
session.save_handler:设置session的储存方式为memcache。默认以文件方式存取session数据,如
果想要使用自定义的处理来存取session数据,比如memcache方式则修为session.save_handler =
memcache
session.save_path:设置session储存的位置,多台memcache用逗号隔开
memcache实现session共享也可以在某个一个应用中设置:
ini_set(“session.save_handler”, “memcache”);
ini_set(“session.save_path”, “tcp://192.168.0.9:11211”);
测试memcache的可用性:

<?php
session_start();
if (!isset($_SESSION['session_time']))
{$_SESSION['session_time'] = time();
}
echo "session_time:".$_SESSION['session_time']."<br />";
echo "now_time:".time()."<br />";
echo "session_id:".session_id()."<br />";
?>

创建测试数据库

create database testab1;
use testab1;
create table test1(id int not null auto_increment,name varchar(20) default
null,primary key(id)) engine=innodb auto_increment=1 default charset=utf8;
insert into test1(name) values ('tom1'),('tom2'),('tom3'),('tom4'),('tom5');
select * from test1;
grant select on testab1.* to user@'%' identified by '123456';

测试memcache是否缓存数据库成功

<?php
$memcachehost = '192.168.42.186';
$memcacheport = 11211;
$memcachelife = 60;
$memcache = new Memcache;
$memcache->connect($memcachehost,$memcacheport) or die ("Could not connect");
$query="select * from test1 limit 10";
$key=md5($query);
if(!$memcache->get($key))
{$conn=mysql_connect("192.168.42.156","user","123456");
mysql_select_db(testdb1);
$result=mysql_query($query);
while ($row=mysql_fetch_assoc($result))
{$arr[]=$row;
}
$f = 'mysql';
$memcache->add($key,serialize($arr),0,30);
$data = $arr ;
}
else{
$f = 'memcache';
$data_mem=$memcache->get($key);
$data = unserialize($data_mem);
}
echo $f;
echo "<br>";
echo "$key";echo "<br>";
//print_r($data);
foreach($data as $a)
{echo "number is <b><font color=#FF0000>$a[id]</font></b>";
echo "<br>";
echo "name is <b><font color=#FF0000>$a[name]</font></b>";
echo "<br>";
}
?>

如果出现mysql表示memcached中没有内容,需要memcached从数据库中取得
再刷新页面,如果有memcache标志表示这次的数据是从memcached中取得的。
memcached有个缓存时间默认是1分钟,过了一分钟后,memcached需要重新从数据库中取得数据

分布式缓存之memcached以及LAMP的搭建相关推荐

  1. 分布式缓存系统Memcached简介与实践(.NET memcached client library)

    原文:分布式缓存系统Memcached简介与实践(.NET memcached client library) 缘起: 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加 ...

  2. Linux分布式缓存系统——memcached+LAMP环境搭建+监控

    概述 memcached简介 Memcached是一个开源.高性能.分布式内存对象缓存系统. Memcached是一种基于内存的key-value存储,用来存储小块的任意数据(字符串.对象),这些数据 ...

  3. memcached java 客户端优化,分布式缓存技术memcached学习系列(五)—— memcached java客户端的使用...

    Memcached的客户端简介 我们已经知道,memcached是一套分布式的缓存系统,memcached的服务端只是缓存数据的地方,并不能实现分布式,而memcached的客户端才是实现分布式的地方 ...

  4. .NET下实现分布式缓存系统Memcached

    [IT168 技术文档]在Web应用程序中,数据通常保存在RDBMS中,应用服务器从数据库中读取数据并在浏览器中显示.但随着数据量的增大.访问的集中,就会出现RDBMS的负载加重.数据库响应变慢.网站 ...

  5. 分布式缓存技术memcached学习系列(五)—— memcached java客户端的使用

    Memcached的客户端简介 我们已经知道,memcached是一套分布式的缓存系统,memcached的服务端只是缓存数据的地方,并不能实现分布式,而memcached的客户端才是实现分布式的地方 ...

  6. 分布式缓存系统Memcached简介与实践

    缘起: 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加了数据库负载.缓存是解决这个问题的好办法.但是ASP.NET中的虽然已经可以实现对页面局部进行缓存,但还是不够灵 ...

  7. php分布式缓存系统 Memcached 入门

    Memcached 是一个分布式的缓存系统, 但是 Memcachd 到底是什么意思,有什么作用呢?缓存一般用来保存一些经常被存取的数据和资源(例如:浏览器会将访问过的网页会话缓存起来),因为通过缓存 ...

  8. 分布式缓存系统 Memcached 【转载】

    本文转载自 http://www.cnblogs.com/zjneter/archive/2007/07/19/822780.html 缘起: 在数据驱动的web开发中,经常要重复从数据库中取出相同的 ...

  9. java分布式缓存memcached_分布式缓存系统Memcached学习心得

    缘起: 在数据驱动的web开发中,经常要重复从数据库中取出相同的数据,这种重复极大的增加了数据库负载.缓存是解决这个问题的好办法. Memcached是什么? Memcached是由Danga Int ...

最新文章

  1. “产教融合新范式,校企聚力新实践”——2018杭州云栖大会大学合作专场论坛成功举办...
  2. Selenium3自动化测试——11. 下拉框处理
  3. mysql 更新 字段 递增_MySQL使用递增变量更新字段
  4. 电脑磁盘清理_软件 | 功能强大的电脑磁盘清理工具中文优化版,有了它,你的电脑就像德芙巧克力一般丝滑...
  5. JAVA在线编译,无需环境变量
  6. 2017-08-16 BEX5下集成FullCalendar
  7. 【转帖】Eclipse快捷键指南
  8. 圆与平面的接触面积_如果把绝对圆的球体放在绝对平的平面上,那接触面是不是无限小?...
  9. django url 路由设置技巧
  10. Java comparator接口源码解读
  11. 如何用TC群控系统同时控制上百台手机
  12. filter java 意思_在JAVA中filter有什么作用?
  13. 怎么创建css样式表,怎样创建可反复使用的外部CSS样式表?
  14. springboot+vue+elementUI 校园志愿者管理系统#毕业设计
  15. 穆大叔:18年生涯让我抬头挺胸 我是像士兵般离开
  16. 哪个ppt模板网站好
  17. 华为鸿蒙cpu,华为转投第三大CPU架构RISC-V?首款鸿蒙开发板曝光
  18. 数字IC面试手撕代码(一)
  19. 2020年焊工(技师)考试资料及焊工(技师)考试申请表
  20. 怎样在几何画板中画数轴

热门文章

  1. 类蛇毒肽、蛇毒肽、 三肽-3、823202-99-9
  2. 有可以在家做的赚钱兼职吗?
  3. 含泪整理最优质美食壁纸素材,你想要的这里都有
  4. python.opencv.imread读图顺序:从上到下,从左到右
  5. JavaScript框架篇——zepto
  6. Node的数据库编程
  7. 修复Adobe Flash Player
  8. ERP与MBA的关系
  9. 搭建自己的ngrok服务(内网穿透 使用简单)
  10. 计算机网络实验报告:【验证性实验】