Windows 下安装 mongoDB

1, 下载


http://www.mongodb.org/downloads

2, 解压后就直接可以使用了, 所有程序都在 bin 目录下.

#解压(安装)目录:
    D:\Program Files\mongodb\

#数据目录(自定义, 需要自己手动建):
    E:\my_file\mongodb_data\data

#日志文件(自定义, 日志目录需要自己手动建):
    E:\my_file\mongodb_data\log\server_log.txt

3, 为了使用方便, 将 mongoDB 注册成系统服务

# 把 mongod 注册成一个系统服务
#   特别注意:
#     --dbpath, --logpath 所带参数的文件夹名字中一定不能有空格, 否则会出现服务注册不成功
"D:\Program Files\mongodb\bin\mongod.exe" --dbpath="E:\my_file\mongodb_data\data" --logpath="E:\my_file\mongodb_data\log\server_log.txt" --install

4, 注册成系统服务后, 我们可以通过命令启动 mongoDB 服务

# 开始->运行->cmd->进入到命令行模式
cmd

# 开启 mongoDB 服务
# 我们可以将这一句保存为 server_launch.bat 批处理文件, 双击它就启动服务
net start "MongoDB"

# 关闭 mongoDB 服务
# 我们可以将这一句保存为 server_stop.bat 批处理文件, 双击它就停止服务
net stop "MongoDB"

5, 进入客户端的方法

cmd

# 进入到 mongoDB 安装目录
D:
cd "Program Files\mongodb\bin"

#打开客户端程序
mongo.exe

6, mongoDB 图形界面管理工具 rock_mongo (中文)


http://code.google.com/p/rock-php/wiki/rock_mongo_zh
Posted in NoSQL | Tagged , , | Leave a comment

C 操作 MySql

1, 启动 mysql 服务

#我安装的是 lampp , 安装路径是 /opt/lampp/lampp
/opt/lampp/lampp start

2, 查询 mysql_config 位置

whereis mysql_config
# 显示位置为 /opt/lampp/bin/mysql_config

3, 编写测试脚本 test_mysql.c

/* Simple C program that connects to MySQL Database server */
#include <stdio.h>
#include <mysql.h>
#include <stdlib.h>
void main() {
    MYSQL *conn;
    MYSQL_RES *res;
    MYSQL_ROW row;

    char *server = "localhost";
    char *user = "root";
    char *password = ""; /* 此处改成你的密码 */
    char *database = "cdcol";

    conn = mysql_init(NULL);

    /* Connect to database */
    if (!mysql_real_connect(conn, server,
          user, password, database, 0, NULL, 0)) {
        fprintf(stderr, "%s\n", mysql_error(conn));
        exit(1);
    }

    /* send SQL query */
    if (mysql_query(conn, "show tables")) {
        fprintf(stderr, "%s\n", mysql_error(conn));
        exit(1);
    }

    res = mysql_use_result(conn);

    /* output table name */
    printf("MySQL Tables in mysql database:\n");
    while ((row = mysql_fetch_row(res)) != NULL)
        printf("%s \n", row[0]);
    mysql_free_result(res);

    mysql_query(conn,"SET NAMES utf8");
	if(mysql_query(conn,"SELECT * FROM cds")) {
		printf("Query Error!\n");
		exit(1);
	}
	res = mysql_use_result(conn);
	printf("The result is:\n");
	while((row=mysql_fetch_row(res))!=NULL) {
		printf("%s \t| %s \t| %s \t| %s\n", row[0], row[1], row[2], row[3]);
	}
	mysql_free_result(res);

    /* close connection */
    mysql_close(conn);
}

4, 编译

gcc $(/opt/lampp/bin/mysql_config --cflags) test_mysql.c -o test_mysql $(/opt/lampp/bin/mysql_config --libs)

5, 运行看效果吧

./test_mysql

P.S. 关于 mysql_config

MySQL中有一个特殊的脚本, 叫做mysql_config. 它会为你编译MySQL客户端,并连接到MySQL服务器提供有用的信息.你需要使用下面两个选项.
-–libs 选项 - 连接MySQL客户端函数库所需要的库和选项.
–-cflags 选项 - 使用必要的include文件的选项等等.
Posted in Linux, Mysql, shell | Tagged , , | Leave a comment

Linux下SVN客户端版本库定时更新

现有两台机器
一台 windows : 192.168.1.125
一台 linux : 192.168.1.132 (Ubuntu 10.04 LTS / root)

windows 上运行有 SVN-Server (svn://192.168.1.125)
Linux 上安装有 SVN-Client , 现在想定时(每一小时)更新一次 Linux 上的版本库.

1, 先将 SVN-Server 上的版本库检出到 Linux 机器的指定目录 (/root/backup/winsvn/)

cd /root/
mkdir backup
cd backup/
mkdir winsvn
cd winsvn/
/usr/bin/svn checkout svn://192.168.1.125 .

2, 设置 crontab

crontab -e

#将 crontab 中的内容修改如下
#第一条是定时同步时钟的,
#第二条才是我们要的, 表示每小时的第50分钟执行一次 SVN 更新命令
#  注意:
#  LANG=en_HK.UTF-8 <-- 这一句话很重要,要将crontab的编码设置成系统环境编码,
#                       否则会造成手动执行 update 命令成功,但放到 crontab 中更新不成功
LANG=en_HK.UTF-8
# m h  dom mon dow   command
19 * * * * /usr/sbin/ntpdate ntp.api.bz
50 * * * * /usr/bin/svn update /root/backup/winsvn --username kuco --password kucopwd --no-auth-cache > /root/backup/winsvn_backup.log

P.S. 特别注意 LANG=en_HK.UTF-8 很重要, 在这个问题郁闷了很久. 可以通过 export 命令显示系统环境编码.

还有几点零星的知识点也一并记录在这里吧 :)

1, SVN客户端检出的时候把用户名和密码都保存了,如果想再切换成其它的用户来检出该怎么操作?

# windows 下
方法1:对于TortoiseSVN软件,右键出TortoiseSVN菜单Settings->Saved Data->Authentication data,Clear
方法2:C:\Documents and Settings\Administrator\Application Data\Subversion\auth

# linux 下
rm -rf ~/.subversion/auth

# 原文地址
# http://blog.chinaunix.net/space.php?uid=20564848&do=blog&cuid=2200464

2, find 命令

# 在当前目录下查找文件名为 rsyslog.conf 的文件
find . -name "rsyslog.conf"

# find 命令详细介绍
# http://www.linuxsir.org/main/?q=node/137

3, 打开 crontab 日志功能

# 默认情况下 ubuntu 执行 crontab 是没有记录日志的, 我们要手动打开
vim /etc/rsyslog.conf

# 发现 rsyslog.conf 调用了 /etc/rsyslog.d/*.conf
ls /etc/rsyslog.d/*.conf

# 先备份
cp /etc/rsyslog.d/50-default.conf /etc/rsyslog.d/50-default.conf.bak

# 再编辑
vim /etc/rsyslog.d/50-default.conf

# 将下面这一行前面的 # 去掉
#cron.*  /var/log/cron.log

# 重启日志服务
cd /etc/init.d/
service rsyslog restart

# 这样 crontab 执行的日志就会记录在
/var/log/cron.log
Posted in Linux, shell | Tagged , , | Leave a comment

开启SVN-Server上的密码认证功能

之前介绍的《Windows 下安装 SVN-Server》, 在安装好 SVN-Server 后可以不需要用户名和密码直接对版本库进行检出/更新/提交等操作, 这样在安全性方面很差, 现在将介绍怎么样在基于 http 协议的 SVN-Server 上添加密码认证功能.

首先假设现在已经存在一个版本库game,
它在 svn_server 上存放的路径是: E:\svn_server\game
客户端 checkout 的地址是: http://localhost/svn/game
我们需要给这个版本库加上用户名密码认证功能.

1, 首先在 E:\svn_server\game\conf\ 目录中新建一个名为 passwd.win 的空文件, 它将记录我们要认证的用户名和密码.

2, 假设我们 Apache 的安装目录是 D:\Program Files\EasyPHP-5.3.2i\apache\ , 我们输入命令生成一个用户名为 admin , 密码是 123456 的帐号

cmd
D:
cd D:\Program Files\EasyPHP-5.3.2i\apache\bin
htpasswd -bm E:\svn_server\game\conf\passwd.win admin 123456

3, 修改 E:\svn_server\game\conf\authz 文件, 修改 [groups] 区块, 再在文件最底部添加上 [game:/]

[groups]
group_admin = admin

[game:/]
@group_admin = rw
* =

4, 修改 Apache 配置文件

//之前我们配置的是下面的代码, 它是对建立在 E:\svn_server 目录下的所有版本库全部生效的
<Location /svn>
DAV svn
SVNParentPath E:\svn_server
</Location>

//如果在 E:\svn_server 目录下有两个版本库
E:\svn_server\game\
E:\svn_server\profile\

//我们只要对 game 库进行密码验证, 对 profile 库不需要验证, 我们就要将上面的 <Location /svn> 区块删除掉, 替换成针对单个版本库生效的代码, 如下:
<Location /svn/profile>
DAV svn
SVNPath E:/svn_server/profile
</Location>

<Location /svn/game>
DAV svn
SVNPath E:/svn_server/game
AuthzSVNAccessFile E:/svn_server/game/conf/authz
Satisfy Any
Require valid-user
AuthType Basic
AuthName "Subversion repository"
AuthUserFile E:/svn_server/game/conf/passwd.win
</Location>

5, 重启 Apache 后, 再用 svn 客户端程序更新本地 game 版本库, 就会弹出用户名/密码认证框, 输入上面设置的 admin/123456 后即可成功更新.

P.S. 如果 SVN-Server 做为一个独立的服务运行在服务器上(即不依赖于 Apache)时, 权限认证设置会简单很多, 只需要将 svnserve.conf 文件中相应的认证开关打开, 然后在 passwd 文件中添加用户名和密码, 再在 authz 做出目录访问权限控制的设置就可以了.

Posted in Apache, Tool | Tagged | Leave a comment

通过rsync定期备份windows下svn目录到linux

利用 rsync 命令备份 windows 下 svn 目录到 linux 服务器上

大体思路是:
先把 windows 下的 svn 目录导出到一个文件夹中(这样不会有多余的 .svn 目录存在), 然后再通过 winRAR 将这个目录打包成 *.rar 文件, 再然后通过 rsync 命令将这个打包好的文件同步到 linux 服务器.

先介绍一下基本环境.

#IP地址:
windows 192.168.1.138
linux 192.168.1.132

#windows下相关软件安装目录:
svn 安装目录    D:\Program Files\svn-win32-1.6.16\bin\svn.exe
winRAR 安装目录 C:\Program Files\WinRAR\WinRAR.exe
rsync 安装目录  D:\Program Files\cwRsync\bin\rsync.exe

OK, 开始操作吧.

1, linux 下的 rsync 安装可以参考这里:


http://www.linuxsir.org/main/?q=node/256

Ubuntu下可以直接用命令安装:
sudo apt-get install rsync

2, 配置 linux 上的 rsync-server

#创建目录和文件
mkdir /etc/rsyncd
touch /etc/rsyncd/rsyncd.conf
touch /etc/rsyncd/rsyncd.secrets
chmod 600 /etc/rsyncd/rsyncd.secrets
touch /etc/rsyncd/rsyncd.motd
#修改配置文件内容
# 详细说明见 http://rsync.samba.org/ftp/rsync/rsyncd.conf.html
# /etc/rsyncd/rsyncd.conf 内容如下
pid file = /var/run/rsyncd.pid
uid = root
gid = root
hosts allow=*
read only = no

[snsgamebak]
path = /home/backup/socialgame/
auth users = root
secrets file = /etc/rsyncd/rsyncd.secrets
# /etc/rsyncd/rsyncd.secrets 内容如下
root:123456

3, 启动 rsync-server

/usr/bin/rsync --daemon --config=/etc/rsyncd/rsyncd.conf
#检查一下
ps -ef | grep rsync

4, windows 下的 rsync 软件( cwRsync_4.1.0_Installer.zip )可以到这里去下载:


http://sourceforge.net/projects/sereds/files/cwRsync/4.1.0/

5, 配置 windows 上的 rsync

#修改配置文件内容
# e:/ggg/rsyncd.secrets 内容如下
123456

6, 测试一下将 windows 上 e:/ttt/ 目录下的所有文件及子目录 rsync 到 linux 服务器

D:
cd "Program Files/cwRsync/bin/"
rsync -r /cygdrive/e/ttt/ root@192.168.1.132::snsgamebak --password-file=/cygdrive/e/ggg/rsyncd.secrets

说明:

因为在 rsync 命令中冒号:有特殊意义, 所以上面的命令中 E: 盘用 /cygdrive/e 表示.
命令中的 snsgamebak 对应的是 linux 上 /etc/rsyncd/rsyncd.conf 中的 [snsgamebak]
上面的命令会将 e:/ttt/ 目录下的所有文件及子目录同步到 linux 服务器上的 /home/backup/socialgame/ 目录下.

7, 编写 bak_rsync.bat 程序,
实现的功能是将 svn 目录(E:\www\game) 先更新
然后再导出到备份目录(E:\ggg\bak\20110608\), 备份目录是自动生成的.
再调用 winrar 将备份目录压缩成 rar 文件, 并删除掉备份目录
再将 rar 文件 rsync 到 linux 服务器
最后删除本地备份 rar 文件, 并返回主目录

bak_rsync.bat 文件内容如下

@echo ======[     开始备份      ]======
@echo off

set svntool="D:\Program Files\svn-win32-1.6.16\bin\svn.exe"
set winrartool="C:\Program Files\WinRAR\WinRAR.exe"
set rsynctool="D:\Program Files\cwRsync\bin\rsync.exe"

set filename=bak_%date:~0,10%

@echo 1, 更新svn目录
%svntool% update E:\www\game

@echo 2, 寻出svn目录到备份文件夹
%svntool% export E:\www\game E:\ggg\bak\%filename%

@echo 3, 检查是否有同名的备份文件, 如果有就删除
cd bak
IF EXIST %filename%.rar del /F /S /Q %filename%.rar

@echo 4, 将备份文件夹压缩成备份文件
%winrartool% m -r %filename%.rar %filename%\*

@echo 5, 删除备份文件夹
rmdir %filename% /Q

@echo 7, 同步到linux服务器
%rsynctool% -r /cygdrive/e/ggg/bak/%filename%.rar root@192.168.1.132::snsgamebak --password-file=/cygdrive/e/ggg/rsyncd.secrets

@echo 8, 删除本地备份文件
del %filename%.rar /Q

@echo 6, 返回主目录
cd ..

8, 将 bak_rsync.bat 加到任务计划中去定期执行.

P.S. 其实还有一个更简单的方法就是直接在 132 那台机器上装上 svn , 直接 checkout windows下的svn-server.

Posted in Linux, Tips, Tool | Tagged | Leave a comment

MongoDB命令集合

基本操作

db.AddUser(username,password)  //添加用户
db.auth(usrename,password)     //设置数据库连接验证
db.cloneDataBase(fromhost)     //从目标服务器克隆一个数据库
db.commandHelp(name)           //returns the help for the command
db.copyDatabase(fromdb,todb,fromhost)  //复制数据库fromdb---源数据库名称,todb---目标数据库名称,fromhost---源数据库服务器地址
db.createCollection(name,{size:3333,capped:333,max:88888})  //创建一个数据集,相当于一个表
db.currentOp()                 //取消当前库的当前操作
db.dropDataBase()              //删除当前数据库
db.eval(func,args)             //run code server-side
db.getCollection(cname)        //取得一个数据集合,同用法:db['cname'] or
db.getCollenctionNames()       //取得所有数据集合的名称列表
db.getLastError()              //返回最后一个错误的提示消息
db.getLastErrorObj()           //返回最后一个错误的对象
db.getMongo()                  //取得当前服务器的连接对象get the server
db.getMondo().setSlaveOk()     //allow this connection to read from then nonmaster membr of a replica pair
db.getName()                   //返回当操作数据库的名称
db.getPrevError()              //返回上一个错误对象
db.getProfilingLevel()
db.getReplicationInfo()        //获得重复的数据
db.getSisterDB(name)           //get the db at the same server as this onew
db.killOp()                    //停止(杀死)在当前库的当前操作
db.printCollectionStats()      //返回当前库的数据集状态
db.printReplicationInfo()
db.printSlaveReplicationInfo()
db.printShardingStatus()       //返回当前数据库是否为共享数据库
db.removeUser(username)        //删除用户
db.repairDatabase()            //修复当前数据库
db.resetError()
db.runCommand(cmdObj)          //run a database command. if cmdObj is a string, turns it into {cmdObj:1}
db.setProfilingLevel(level)    //0=off,1=slow,2=all
db.shutdownServer()            //关闭当前服务程序
db.version()                   //返回当前程序的版本信息

数据集(表)操作

db.test.find({id:10})          //返回test数据集ID=10的数据集
db.test.find({id:10}).count()  //返回test数据集ID=10的数据总数
db.test.find({id:10}).limit(2) //返回test数据集ID=10的数据集从第二条开始的数据集
db.test.find({id:10}).skip(8)  //返回test数据集ID=10的数据集从0到第八条的数据集
db.test.find({id:10}).limit(2).skip(8)  //返回test数据集ID=1=的数据集从第二条到第八条的数据
db.test.find({id:10}).sort()   //返回test数据集ID=10的排序数据集
db.test.findOne([query])       //返回符合条件的一条数据
db.test.getDB()                //返回此数据集所属的数据库名称
db.test.getIndexes()           //返回些数据集的索引信息
db.test.group({key:...,initial:...,reduce:...[,cond:...]})
db.test.mapReduce(mayFunction,reduceFunction,<optional params>)
db.test.remove(query)                      //在数据集中删除一条数据
db.test.renameCollection(newName)          //重命名些数据集名称
db.test.save(obj)                          //往数据集中插入一条数据
db.test.stats()                            //返回此数据集的状态
db.test.storageSize()                      //返回此数据集的存储大小
db.test.totalIndexSize()                   //返回此数据集的索引文件大小
db.test.totalSize()                        //返回些数据集的总大小
db.test.update(query,object[,upsert_bool]) //在此数据集中更新一条数据
db.test.validate()                         //验证此数据集
db.test.getShardVersion()                  //返回数据集共享版本号

MongoDB语法与现有关系型数据库SQL语法比较

db.test.find({'name':'foobar'})
  // SELECT * FROM test WHERE name='foobar'
db.test.find()
  // SELECT * FROM test
db.test.find({'data_id':10}).count()
  // SELECT COUNT(*) FROM test WHERE data_id=10
db.test.find().skip(10).limit(20)
  // SELECT * FROM test LIMIT 10,20
db.test.find({'data_id':{$in:[25,35,45]}})
  // SELECT * FROM test WHERE data_id IN (25,35,45)
db.test.find().sort({'data_id':-1})
  // SELECT * FROM test ORDER BY data_id DESC
db.test.distinct('name',{'data_id':{$lt:20}})
  // SELECT DISTINCT(name) FROM test WHERE data_id<20
db.test.group({key:{'name':true},cond:{'name':'foo'},reduce:function(obj,prev){prev.msum+=obj.marks;},initial:{msum:0}})
  // SELECT name,SUM(marks) FROM test GROUP BY name
db.test.find('this.data_id<20',{name:1})
  // SELECT name FROM test WHERE data_id<20
db.test.insert({'name':'foobar','age':25})
  // INSERT INTO test ('name','age') VALUES('foobar',25)
db.test.remove({})
  // DELETE * FROM test
db.test.remove({'age':20})
  // DELETE test WHERE age=20
db.test.remove({'age':{$lt:20}})
  // SELETE test WHERE age<20
db.test.remove({'age':{$lte:20}})
  // DELETE test WHERE age<=20
db.test.remove({'age':{$gt:20}})
  // DELETE test WHERE age>20
db.test.remove({'age':{$gte:20}})
  // DELETE test WHERE age>=20
db.test.remove({'age':{$ne:20}})
  // DELETE test WHERE age!=20
db.test.update({'name':'foobar'},{$set:{'age':36}})
  // UPDATE test SET age=36 WHERE name='foobar'
db.test.update({'name':'foobar'},{$inc:{'age':3}})
  // UPDATE test SET age=age+3 WHERE NAME='foobar'
Posted in NoSQL | Tagged , | Leave a comment

Redis命令集合

常规操作命令

exits key              //测试指定key是否存在,返回1表示存在,0不存在
del key1 key2 ....keyN //删除给定key,返回删除key的数目,0表示给定key都不存在
type key               //返回给定key的value类型。返回 none 表示不存在key,string字符类型,list 链表类型 set 无序集合类型...
keys pattern           //返回匹配指定模式的所有key,下面给个例子
randomkey              //返回从当前数据库中随机选择的一个key,如果当前数据库是空的,返回空串
rename oldkey newkey   //原子的重命名一个key,如果newkey存在,将会被覆盖,返回1表示成功,0失败。可能是oldkey不存在或者和newkey相同
renamenx oldkey newkey //同上,但是如果newkey存在返回失败
dbsize                 //返回当前数据库的key数量
expire key seconds     //为key指定过期时间,单位是秒。返回1成功,0表示key已经设置过过期时间或者不存在
ttl key                //返回设置过过期时间的key的剩余过期秒数 -1表示key不存在或者没有设置过过期时间
select db-index        //通过索引选择数据库,默认连接的数据库所有是0,默认数据库数是16个。返回1表示成功,0失败
move key db-index      //将key从当前数据库移动到指定数据库。返回1成功。0 如果key不存在,或者已经在指定数据库中
flushdb                //删除当前数据库中所有key,此方法不会失败。慎用
flushall               //删除所有数据库中的所有key,此方法不会失败。更加慎用

string 类型数据操作命令

set key value         //设置key对应的值为string类型的value,返回1表示成功,0失败
setnx key value       //同上,如果key已经存在,返回0 。nx 是not exist的意思
get key               //获取key对应的string值,如果key不存在返回nil
getset key value      //原子的设置key的值,并返回key的旧值。如果key不存在返回nil
mget key1 key2 ... keyN            //一次获取多个key的值,如果对应key不存在,则对应返回nil。下面是个实验,首先清空当前数据库,然后设置k1,k2.获取时k3对应返回nil
mset key1 value1 ... keyN valueN   //一次设置多个key的值,成功返回1表示所有的值都设置了,失败返回0表示没有任何值被设置
msetnx key1 value1 ... keyN valueN //同上,但是不会覆盖已经存在的key
incr key              //对key的值做加加操作,并返回新的值。注意incr一个不是int的value会返回错误,incr一个不存在的key,则设置key为1
decr key              //同上,但是做的是减减操作,decr一个不存在key,则设置key为-1
incrby key integer    //同incr,加指定值 ,key不存在时候会设置key,并认为原来的value是 0
decrby key integer    //同decr,减指定值。decrby完全是为了可读性,我们完全可以通过incrby一个负值来实现同样效果,反之一样。
append key value      //给指定key的字符串值追加value,返回新字符串值的长度。下面给个例子
substr key start end  //返回截取过的key的字符串值,注意并不修改key的值。下标是从0开始的,接着上面例子

list 类型数据操作命令

lpush key string          //在key对应list的头部添加字符串元素,返回1表示成功,0表示key存在且不是list类型
rpush key string          //同上,在尾部添加
llen key                  //返回key对应list的长度,key不存在返回0,如果key对应类型不是list返回错误
lrange key start end      //返回指定区间内的元素,下标从0开始,负值表示从后面计算,-1表示倒数第一个元素 ,key不存在返回空列表
ltrim key start end       //截取list,保留指定区间内元素,成功返回1,key不存在返回错误
lset key index value      //设置list中指定下标的元素值,成功返回1,key或者下标不存在返回错误
lrem key count value      //从key对应list中删除count个和value相同的元素。count为0时候删除全部
lpop key                  //从list的头部删除元素,并返回删除元素。如果key对应list不存在或者是空返回nil,如果key对应值不是list返回错误
rpop                      //同上,但是从尾部删除
blpop key1...keyN timeout //从左到右扫描返回对第一个非空list进行lpop操作并返回,比如blpop list1 list2 list3 0 ,如果list不存在list2,list3都是非空则对list2做lpop并返回从list2中删除的元素。如果所有的list都是空或不存在,则会阻塞timeout秒,timeout为0表示一直阻塞。当阻塞时,如果有client对key1...keyN中的任意key进行push操作,则第一在这个key上被阻塞的client会立即返回。如果超时发生,则返回nil。有点像unix的select或者poll
brpop                     //同blpop,一个是从头部删除一个是从尾部删除
rpoplpush srckey destkey  //从srckey对应list的尾部移除元素并添加到destkey对应list的头部,最后返回被移除的元素值,整个操作是原子的.如果srckey是空或者不存在返回nil

set 类型数据操作命令

sadd key member                //添加一个string元素到,key对应的set集合中,成功返回1,如果元素以及在集合中返回0,key对应的set不存在返回错误
srem key member                //从key对应set中移除给定元素,成功返回1,如果member在集合中不存在或者key不存在返回0,如果key对应的不是set类型的值返回错误
spop key                       //删除并返回key对应set中随机的一个元素,如果set是空或者key不存在返回nil
srandmember key                //同spop,随机取set中的一个元素,但是不删除元素
smove srckey dstkey member     //从srckey对应set中移除member并添加到dstkey对应set中,整个操作是原子的。成功返回1,如果member在srckey中不存在返回0,如果key不是set类型返回错误
scard key                      //返回set的元素个数,如果set是空或者key不存在返回0
sismember key member           //判断member是否在set中,存在返回1,0表示不存在或者key不存在
sinter key1 key2...keyN        //返回所有给定key的交集
sinterstore dstkey key1...keyN //同sinter,但是会同时将交集存到dstkey下
sunion key1 key2...keyN        //返回所有给定key的并集
sunionstore dstkey key1...keyN //同sunion,并同时保存并集到dstkey下
sdiff key1 key2...keyN         //返回所有给定key的差集
sdiffstore dstkey key1...keyN  //同sdiff,并同时保存差集到dstkey下
smembers key                   //返回key对应set的所有元素,结果是无序的

sorted set 类型数据操作命令

zadd key score member        //添加元素到集合,元素在集合中存在则更新对应score
zrem key member              //删除指定元素,1表示成功,如果元素不存在返回0
zincrby key incr member      //增加对应member的score值,然后移动元素并保持skip list保持有序。返回更新后的score值
zrank key member             //返回指定元素在集合中的排名(下标),集合中元素是按score从小到大排序的
zrevrank key member          //同上,但是集合中元素是按score从大到小排序
zrange key start end         //类似lrange操作从集合中去指定区间的元素。返回的是有序结果
zrevrange key start end      //同上,返回结果是按score逆序的
zrangebyscore key min max    //返回集合中score在给定区间的元素
zcount key min max           //返回集合中score在给定区间的数量
zcard key                    //返回集合中元素个数
zscore key element           //返回给定元素对应的score
zremrangebyrank key min max  //删除集合中排名在给定区间的元素
zremrangebyscore key min max //删除集合中score在给定区间的元素

hash 类型数据操作命令

hset key field value       //设置hash field为指定值,如果key不存在,则先创建
hget key field             //获取指定的hash field
hmget key filed1....fieldN //获取全部指定的hash filed
hmset key filed1 value1 ... filedN valueN //同时设置hash的多个field
hincrby key field integer  //将指定的hash filed 加上给定值
hexists key field          //测试指定field是否存在
hdel key field             //删除指定的hash field
hlen key                   //返回指定hash的field数量
hkeys key                  //返回hash的所有field
hvals key                  //返回hash的所有value
hgetall                    //返回hash的所有filed和value
Posted in NoSQL | Tagged , | Leave a comment

WinSCP 与 Putty 中文显示乱码解决方法

WinSCP:

  1, 打开WinSCP, 在登录会话界面中选定将要登录的会话.
  2, 点击旁边的"编辑"按钮.
  3, 在左侧树型菜单中找到"环境"项, 并打开它.
  4, 在右侧中一项为"文件名UTF-8编码", 选择"开启".
  5, 搞定!

Putty:

  1, 打开Putty.exe, 在登录会话界面中选定Default Settings.
  2, 再点击左侧树形菜单中的"Window -> Translation"
  3, 在右侧界面中有一项"Received data assumed to be in which character set:" 在下拉列表中选择"UTF-8"
  4, 搞定!

将 Putty 与 WinSCP 关联:

  1, 用 WinSCP 登录一个会话.
  2, 菜单 -> 选项 -> 选项 , 打开选项设置面板.
  3, 在左侧树型菜单中找到"集成 -> 应用程序", 并打开它.
  4, 在右侧界面中设置 Putty 的绝对路径, 并将下面的"记住会话密码并传给Putty"勾上
  5, 确定保存
  6, 在菜单下面的快捷工具栏中找到 putty 图标, 点击它即可看到效果. 也可以用 Ctrl+p 快捷键.
Posted in Tips, Tool | Tagged | Leave a comment

MySql 5.5 只能使用 ENGINE 选项指定存储引擎

同事在用 Navicat 8.0 连接测试机上的 MySql 创建数据表时发现老是报语法错误, 而连接自己电脑上的 MySql 并使用相同操作时却能创建成功.

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'TYPE = MYISAM' at line 1

Navicat 8.0 当创建数据表时指定了数据表的存储引擎时生成的 SQL 语句是类似

CREATE TABLE test (id INT) TYPE = MYISAM;

比较了一下两台机器上安装的 MySql 版本, 测试机上的是 5.5 , 本机上的是 5.1 .
跑到 MySql 官网上查了查, 发现在 MySql 5.5 的一点改动, 移除了一些旧的特性, 像指定存储引擎时只能用 ENGINE 选项, 不能使用 TYPE 选项. 而之前的版本是两者都可以使用的.

# Removed Features
The TYPE table option to specify the storage engine for CREATE TABLE or ALTER TABLE (use ENGINE).

同事习惯使用 Navicat 不想使用 phpMyAdmin , 怎么办呢? 下载了个 Navicat 9.0 , 再测试, 一切OK!

Navicat 9.0 下载地址: http://www.xiazaiba.com/html/2122.html
更多的 MySql 5.5 新特性: http://dev.mysql.com/doc/refman/5.5/en/mysql-nutshell.html

Posted in Mysql | Tagged | Leave a comment

Memcache 内存空间划分方法

参考自 这里, 这里, 这里, 这里

假如我们要存放的数据为 200 Bytes , 当向 memcache 存放数据时:

1, memcache 先检查数据的大小, 得到数据尺寸(200 Bytes);
2, 再检查 memcache 已划分过的并且可用的并且自身大小大于数据尺寸的最小容量的 chunk ,
   如果有存在这样的 chunk , 跳到第 4 步, 如果没有跳到第 3 步;
3, memcache 向内存申请 1MB 的空间并将这 1MB 的空间划分为 4096 个大小为 256 Bytes 的 chunk;
   为什么是 4096 个?
       1M = 1024K = 1048576B
       1048576 / 256 = 4096
   为什么是 256 Bytes?
       memcache 根据特定的 growth factor 来对 chunk 的尺寸做增加
       (默认为 1.25, 为了方便描述统一按 2 来进行计算)
       例如所有的 chunk 的尺寸大小都只会下面列表中的一类, 不会出现大小为 100 Bytes 的 chunk.
           64 Bytes,
           128 Bytes
           256 Bytes,
           512 Bytes,
           1024 Bytes,
           2048 Bytes,
           ....
4, memcache 取到一个已划分过的并且可用的并且自身大小大于数据尺寸的最小容量的 chunk , 保存数据.

要注意的点:

1, 第 2 步中提到的"可用的"chunk, "可用的"是指一个空的 chunk 空间或者是一个已有数据但数据已过期的 chunk 空间.
2, 第 3 步中申请的 1MB 内存空间被称为一个 slab, 也叫一个 page
3, 以同样 chunk 大小进行分割的 slab 属于同一组 slab class
4, memcache 的 key 限制为 250 bytes
5, memcache 单个缓存数据大小最大为 1MB(1000000bytes) , 这是由 memcache 的 page 大小限制的.
6, 通过 stats slabs 可以查看各个 slab class 的统计信息
   假设现在一组slab, 它的chunk大小是128KB, total_pages =1, 那么
   total_chunks = (1MB/128KB) * 1 =  8,
   total_chunks=used_chunks + free_chunks,
   free_chunks = 被使用过但是已经释放的chunk个数(注:个人理解)
   free_chunks_end = 没有被使用过的chunk个数(注:个人理解)
   used_chunks = free_chunks_end + 现在存储着数据的chunk个数
Posted in PHP, Tips | Tagged | Leave a comment