桌游马尼拉规则调整乱想

今天跟着同事试着学了一把马尼拉,游戏还不错,不过5个人玩时间倒是长了些,花了快2个小时。

前3回合凭着做海贼的天赋,暴发了一把,后面主要就是靠股票和上船运货稳扎稳打了,最后居然大胜。

今天这局买港口话事权的价格普遍偏高,有一局我居然花了31块大洋买话事权,大家都太冲动了些,都是冲着股票去的。这里的股票只有升值(或者保值),如果改成和现实一样,既有可能涨也有可能跌的话游戏会不会更刺激呢?而且再加上一支海盗的股票,可选择的就更多了。刚开局的时候所有股票价格都为30,货物运送成功1次则股票价格涨1格,最多连涨3格(3次后就算继续运送成功也不涨);货物运送失败1次则股票价格跌1格,同样,最多连跌3格;而海盗每成功劫1条船股票价格涨1格,1回合内没有劫到船则股票价格跌1格,连涨连跌次数同样是3格。这样调整之后,投资股票时则需要更谨慎,购买话事权的时候也或许会更冷静一些。

mysql字符默认不区分大小写?

最近发现短链接服务在生成短链接时经常会发生碰撞,刚开始单纯地以为是生成算法有问题,毕竟就算是4位的短链接也有62^4个链接可能(26个字母的大小写+10个数字),如果生成算法没问题的话发生碰撞的概率应该是较小的。

检查了一遍代码,生成算法也确实有一些问题,但都不是主要问题。今天随手在mysql里select了一下,发现查询的时候居然不区分大小写!那么其实4位的短链接就只有36^4个链接可能(160多万而已)!

查阅了mysql相关文档,大致了解了mysql字符集及校对规则的选取方式:

  1. 如果指定了字符集和校对规则,那么采用指定的字符集和校对规则。
  2. 如果指定了字符集但没有指定校对规则,那么采用指定的字符集和该字符集的默认校对规则。
  3. 否则,采用服务器字符集和服务器校对规则。

可以通过show collation命令查询支持的校对规则及字符集默认的校对规则。
mysql数据库也差不多支撑不住目前的需求了,反正要迁移到分布式数据库了就暂时不理这个问题了。但越来越觉得是应该好好完整地将mysql手册看一遍了。

邮件信头中Return-Path、Reply-To和From的区别

懒得自己写,直接引用一段别人的回复(原贴传送门),大致跟自己之前的实践及查看的文档相符。

1)The Return-Path (sometimes called the Reverse-Path or Envelope-FROM -- all of these terms can be used interchangeably) is the value used during the SMTP session. As you can see, this does not need to be the same value that is actually found in the mail headers. Only the recipient's mail server is supposed to add a Return-Path header to the top of the email. This records the actual Return-Path sender during the SMTP session. If a Return-Path header is already exists in the email, then that header is to be removed, and replaced by the recipient's mail server.

All bounces that occur during the SMTP session should go back to the Return-Path value. Some servers may accept all email, and then queue it locally, until it has a free thread to deliver it to the recipient's mailbox. If the recipient doesn't exist, it should bounce it back to the recorded Return-Path value.

Note, not all mail servers obey this rule. Some mail servers will bounce it back to the FROM address.

2)The FROM address is the value actually found in the FROM header. This is supposed to be who the message is FROM. This is what you see as the "FROM" in most mail clients. If an email does not have a Reply-To header, then all human (mail client) replies should go back to the FROM address.

3)The Reply-To header is added by the sender (or the sender's software). It is where all human replies should be addressed too. Basically, when the user clicks "reply", the Reply-To value should be the value used as the recpient of the newly composed email. The Reply-To value should not be used by any server. It is meant for client side use.

However, as you can tell, not all mail servers obey the RFC standards or recommendations.

数据库表的轮转(续)

上次提到了数据库表的轮转,大致阐述了问题及初步的解决方法。然而实现的时候还是会遇到些问题。

轮转的时候,需要将旧表A中未完成的任务都迁移到新建的表B中(当然也可以不迁移,而是直接将旧表中的任务处理完为止,但这种方式更为复杂曲折,不予考虑)。迁移的时候有可能会往A中继续插入新的任务,迁移可能会遗漏一些记录;或者从A中取出任务执行完后需要更新任务状态时却发现A中该记录已被迁移到B中了,造成任务状态的不确定性;又或者在A中存在某用户U的开通记录但处理时失败了需要继续重试,但迁移过程中继续插入了一条取消记录,那么就有可能取消成功了但是又由于之前有个失败的开通记录,重试后就导致又被开通了。可能存在的问题还有许多,比如有可能新建表或迁移的时候数据库处理失败了。有没办法将创建新表、迁移记录处理成一个原子操作呢?

首先想到的是通过加锁。具体步骤如下:

  1. 创建新表B
  2. 对旧表A和新表B及轮转记录表C都加写锁(lock tables a write, b write, c write;)
  3. 关闭自动提交(set autocommit=0)
  4. 更新轮转记录C
  5. 将旧表A中需要迁移的记录都select出来,然后批量插入到B中
  6. 将sql语句中记录的tableName变量更改成新表B的表名
  7. 更新轮转记录C,标记本次迁移完成
  8. 释放表锁(unlock tables)及其他一些后续处理

但由于对数据库锁天然的畏惧,最终并没有使用该方式,而是通过自己程序内部控制以模拟达到锁的效果。具体步骤如下:

  1. 创建新表B
  2. 设置onCopy=true(onCopy=true时,其他希望更新任务记录的数据库操作都会阻塞在copyLock.wait()上)
    3~7与上述方式一致
  3. 设置onCopy=false,并调用copyLock.notifyAll()以唤醒所有阻塞的数据库操作

这次重构,由于对mysql的了解还不够深入,花费了许多时间,期间详细查看了mysql官方文档关于事务及锁的描述,获益匪浅